package Features;

use vaaneeConfig qw(%C);

@ISA = qw(Exporter);
@EXPORT = qw();
@EXPORT_OK =  qw(%dbs %C);


sub new {
	my($this) = {};

	bless $this;
	return $this;
}

sub print {
	my($this) = shift;
	my($Parameters) = shift;
	my $feat;

	print STDERR "Features ==\n";
	foreach $feat (keys %$this) {
		print STDERR "\t$feat = ".$this->{$feat}."\t";
		print STDERR $Parameters->{$feat} if($Parameters);
		print STDERR "\n";
	}
	print STDERR "===========\n";
}


sub printLine {
	my($this) = shift;
	my $feat;

	foreach $feat (keys %$this) {
		print "$feat = ".$this->{$feat}." ";
	}
	print "\n";
}


sub getsenFeatures {

	my($Features) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($Dep) = shift;
	my($Align) = shift;
	my($purpose) = shift;
	my($nodeId,$i);

	my($nengwords) = $#{$engsen}+1;
	my($nhinwords) = $#{$hinsen}+1;


	for($nodeId=0;$nodeId<$nengwords;$nodeId++) {

		my($LFeatures,$SynFeatures,$GFeatures,$MWEFeatures,$LMFeatures);

		$LFeatures = new Features;
		$SynFeatures = new Features;
		$MWEFeatures = new Features;
		$LMFeatures = new Features;

		$LFeatures->getnodeLFeatures($nodeId,$engsen,$hinsen,$Align->{'aln'}->[$nodeId],$purpose) if(&checkCompat($purpose,"LOCAL"));  
		$Features->addFeatures($LFeatures);

		$SynFeatures->getnodeSynFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"SYN"));
		$Features->addFeatures($SynFeatures);

		$MWEFeatures->getnodeMWEFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"MWE"));
		$Features->addFeatures($MWEFeatures);

		#$LMFeatures->getnodeLMFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"LM"));
		#$Features->addFeatures($LMFeatures);

		if($nodeId==$Dep->[0]->{'root'}) {
			$GFeatures = new Features;
			$GFeatures->getnodeGFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"SYN"));
			$Features->addFeatures($GFeatures);
		}
	}
}


sub getnodeOFeatures {

	my($Features) = shift;
	my($nodeId) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($Dep) = shift;
	my($Align) = shift;
	my($purpose) = shift;


	my($nengwords) = $#{$engsen}+1;
	my($nhinwords) = $#{$hinsen}+1;

	my($GFeatures,$SynFeatures,$MWEFeatures);

	$GFeatures = new Features;
	$SynFeatures = new Features;
	$MWEFeatures = new Features;
	$LMFeatures = new Features;


	$SynFeatures->getnodeSynFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"SYN"));
	$Features->addFeatures($SynFeatures);

	$MWEFeatures->getnodeMWEFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"MWE"));
	$Features->addFeatures($MWEFeatures);

	#$LMFeatures->getnodeLMFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"LM"));
	#$Features->addFeatures($LMFeatures);

	$GFeatures->getnodeGFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"GLOBAL"));
	$Features->addFeatures($GFeatures);
#	print "NodeId = $nodeId, Purpose=$purpose, Setting=$LOCAL, Compat=".&checkCompat($purpose,"LOCAL")."\n";

}

sub getnodeFeaturesNew {

	my($Features) = shift;
	my($srcNode) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($Dep) = shift;
	my($Align) = shift;
	my($purpose) = shift;
	my($children) = shift;


	my($nengwords) = $#{$engsen}+1;
	my($nhinwords) = $#{$hinsen}+1;

	my($LFeatures,$GFeatures,$SynFeatures,$MWEFeatures);

	$LFeatures = new Features;
	$GFeatures = new Features;
	$SynFeatures = new Features;
	$MWEFeatures = new Features;
	$LMFeatures = new Features;

	$srcNode=~/l0~([0-9]+)/;
	$nodeId = $1;

	$LFeatures->getnodeLFeaturesNew($srcNode,$engsen,$hinsen,$Align->{'aln'}->[$nodeId],$purpose) if(&checkCompat($purpose,"LOCAL"));  
	$Features->addFeatures($LFeatures);

	$SynFeatures->getnodeSynFeaturesNew($srcNode,$engsen,$hinsen,$children,$Align,$purpose) if(&checkCompat($purpose,"SYN"));
	$Features->addFeatures($SynFeatures);
	

	my($t,$s) = &getSpanFeatures($srcNode,$Dep,$Align,$purpose);
	if($t==0) {
		$Features->{'zeroSpan'} = 1;
	}
	else {
		$Features->{'tgtSpan'} = $t;
	}
#	$Features->{'srcSpan'} = $s;


#	$MWEFeatures->getnodeMWEFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"MWE"));
#	$Features->addFeatures($MWEFeatures);

	#$LMFeatures->getnodeLMFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"LM"));
	#$Features->addFeatures($LMFeatures);

#	$GFeatures->getnodeGFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"GLOBAL"));
#	$Features->addFeatures($GFeatures);
#	print "NodeId = $nodeId, Purpose=$purpose, Setting=$LOCAL, Compat=".&checkCompat($purpose,"LOCAL")."\n";

}

sub getnodeTransFeats {

	my($Features) = shift;

	my($srcNode) = shift;
	my($tgtNode) = shift;

	my($engsen) = shift;

	my($SDep) = shift;
	my($TDep) = shift;

	my($children) = shift;
	my($purpose) = shift;

	my($nengwords) = $#{$engsen}+1;
	my($nhinwords) = $#{$hinsen}+1;

	my($LFeatures,$GFeatures,$SynFeatures,$MWEFeatures,$LMFeatures);

	$LFeatures = new Features;
	$SynFeatures = new Features;
	$LMFeatures = new Features;

	$srcNode=~/l0~([0-9]+)/;
	$nodeId = $1;
#	print STDERR $tgtNode." is the target node \n";

	$LFeatures->getnodeLTransFeats($srcNode,$tgtNode,$engsen,$SDep,$TDep,$children,$purpose) if(&checkCompat($purpose,"LOCAL"));  
	$Features->addFeatures($LFeatures);
#	print STDERR "\n";
	$SynFeatures->getnodeSynTransFeats($srcNode,$tgtNode,$engsen,$SDep,$TDep,$children,$purpose) if(&checkCompat($purpose,"SYN"));  
	$Features->addFeatures($SynFeatures);

#	print STDERR "Karthik Entering\n";

	
	$LMFeatures->getnodeLMTransFeats($srcNode,$tgtNode,$engsen,$SDep,$TDep,$children,$purpose) if(&checkCompat($purpose,"LM"));  
	$Features->addFeatures($LMFeatures);

}

sub getnodeTransFeatsLocal {

	my($Features) = shift;

	my($srcNode) = shift;
	my($tgtNode) = shift;

	my($engsen) = shift;

	my($SDep) = shift;
	my($TDep) = shift;

	my($children) = shift;
	my($purpose) = shift;

	my($nengwords) = $#{$engsen}+1;
	my($nhinwords) = $#{$hinsen}+1;

	my($LFeatures,$GFeatures,$SynFeatures,$MWEFeatures,$LMFeatures);

	$LFeatures = new Features;
	$SynFeatures = new Features;
	$LMFeatures = new Features;

	$srcNode=~/l0~([0-9]+)/;
	$nodeId = $1;
#	print STDERR $tgtNode." is the target node \n";

	$LFeatures->getnodeLTransFeats($srcNode,$tgtNode,$engsen,$SDep,$TDep,$children,$purpose) if(&checkCompat($purpose,"LOCAL"));  
	$Features->addFeatures($LFeatures);

}

sub getSpanFeatures {
	my($srcNode,$Dep,$Align,$purpose) = @_;
	my($srcWord);
	$srcNode=~/^l0~([0-9]+)/;
	$srcWord=$1;
	my($srcSpan,$tgtSpan);

	my($leftNode,$rightNode,$srcNodes,$tgtNodes) = (200,-1,0,0);
	my($child);
	my(%srcPts,%tgtPts);

	foreach $child (@{$Dep->[$srcWord]->{'attch'}}) {
		my($s,$t) = &getSpanPts($child,$Dep,$Align);
		foreach $srcPt (@$s) {
			$srcPts{$srcPt}=1;
		}
		foreach $tgtPt (@$t) {
			$tgtPts{$tgtPt}=1;
		}
	}

	my(@alnPts) = @{$Align->{'aln'}->[$srcWord]};
	my($alnPt);
	foreach $alnPt (@alnPts) {
		$tgtPts{$alnPt} = 1;
	}
	$srcPts{$srcWord} = 1;


	foreach $tgtPt (keys %tgtPts) {
		if($tgtPt<$leftNode) {
			$leftNode = $tgtPt;
		}
		if($tgtPt>$rightNode) {
			$rightNode = $tgtPt;
		}
	}

	if(scalar(keys %tgtPts)>0) {
		$tgtSpan = ($rightNode-$leftNode+1)/scalar(keys %tgtPts);
		$srcSpan = ($rightNode-$leftNode+1)/scalar(keys %srcPts);
	}
	else {
		$srcSpan = 0;
		$tgtSpan = 0;
	}

	return ($tgtSpan,$srcSpan);
}

sub getSpanPts {
	my ($rootNode,$Dep,$Align) = @_;
	my ($s) = [];
	my ($t) = [];
	push(@$s,$rootNode);
	push(@$t,@{$Align->{'aln'}->[$rootNode]});

	my($child);
	foreach $child (@{$Dep->[$rootNode]->{'attch'}}) {
		my($sTemp,$tTemp) = &getSpanPts($child,$Dep,$Align);
		push(@$s,@$sTemp);
		push(@$t,@$tTemp);
	}

#	print " Child ($rootNode) => ".join('+',@$t)."\n";

	return ($s,$t);
}


sub getnodeFeatures {

	my($Features) = shift;
	my($nodeId) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($Dep) = shift;
	my($Align) = shift;
	my($purpose) = shift;


	my($nengwords) = $#{$engsen}+1;
	my($nhinwords) = $#{$hinsen}+1;

	my($LFeatures,$GFeatures,$SynFeatures,$MWEFeatures);

	$LFeatures = new Features;
	$GFeatures = new Features;
	$SynFeatures = new Features;
	$MWEFeatures = new Features;
	$LMFeatures = new Features;


	$LFeatures->getnodeLFeatures($nodeId,$engsen,$hinsen,$Align->{'aln'}->[$nodeId],$purpose) if(&checkCompat($purpose,"LOCAL"));  
	$Features->addFeatures($LFeatures);

	$SynFeatures->getnodeSynFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"SYN"));
	$Features->addFeatures($SynFeatures);

	$MWEFeatures->getnodeMWEFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"MWE"));
	$Features->addFeatures($MWEFeatures);

	#$LMFeatures->getnodeLMFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"LM"));
	#$Features->addFeatures($LMFeatures);

	$GFeatures->getnodeGFeatures($nodeId,$engsen,$hinsen,$Dep,$Align,$purpose) if(&checkCompat($purpose,"GLOBAL"));
	$Features->addFeatures($GFeatures);
#	print "NodeId = $nodeId, Purpose=$purpose, Setting=$LOCAL, Compat=".&checkCompat($purpose,"LOCAL")."\n";

}

sub getnodeMWEFeatures {
	my($this) = shift;
	my($sword) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($Align)= shift;

	return $this;
}

sub getnodeLMFeatures {
	my($this) = shift;
	my($sword) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($Dep) = shift;
	my($Align)= shift;
	my($purpose) = shift;
	
	my(@openlist);
	push(@openlist,$sword);
	my(%hinMarked);

	my($str,$s);

	$str="";
	while($element=pop(@openlist)) {
		my(@aln);
		@aln = @{$Align->{'aln'}};	
		foreach $s (sort {$a<=>$b} @aln) {
			$hinMarked{$s} = 1;
		}

		foreach $child (@{$Dep->[$element]->{'attch'}}) {
			push(@openlist,$child);
		}
	}

	foreach $s(sort {$a<=>$b} keys %$hinMarked) {
		$str.=$hinsen->[$s]->{'word'}."_";
	}
	$str=~s/_$//g;
	my($lmScr) = &lmscore($str);

	$this->{'lm'} = $lmScr;

	return $this;
}

sub lmscore {

	my($string);
	$string = $_[0];
	
	open(TMP,">/tmp/lmstring.$$.txt");
	$string=~s/^\s*//g; $string=~s/\s*$//g; $string=~s/_+/ /g;
	print TMP $string;
	close(TMP);
	
	my($lmscore) = `./scripts/string2fst2.pl < /tmp/lmstring.$$.txt | fsmcompile -i ~/corpus/hnd_50k.txt.wl | fsmcompose ~/corpus/hnd_50k-5k.txt.lm.fst - | fsmrmepsilon | fsmbestpath | fsmprint -i ~/corpus/hnd_50k.txt.wl | ./scripts/getlmscore.pl`;
	chomp($lmscore);

	return $lmscore;

}

sub getnodeSynFeaturesNew {

	my($this) = shift;
	my($snode) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($children) = shift;
	my($Align)= shift;
	my($purpose) = shift;

	my(%featuresSet);

	if(@$children==0) {
		return $this;
	}

	my %srcwords = ();
	$snode=~/l0~([0-9]+)/;
	$sword = $1;
	$srcwords{ $sword } = 1;
	foreach $child (@{$children}) 
	{
		$srcwords{ $child } = 1;
	}

	#print "Getting divergence for node $sword\n";
	my($time) = time() ;

	my $src_array = "";
	my %tgtwords = ();
	my %mapping = ();
	my $src;
	my $i = 1;
	my ($minPos);
	my ($maxPos);

	foreach $src (sort {$a<=>$b} keys %srcwords)
	{
		my $tgt_min = 10000;  
		my $tgt_max = -1;  
		foreach $tgt (@{$Align->{'aln'}->[$src]})
		{
			if($tgt_min > $tgt)
			{
				$tgt_min = $tgt;
			}
			if($tgt_max < $tgt)
			{
				$tgt_max = $tgt;
			}
		}
		$minPos->{$src} = $tgt_min;
		$maxPos->{$src} = $tgt_max;
	}

	%mapping = ();
	foreach $src (sort {$a<=>$b} keys %srcwords)
	{
		if( $src  == $sword) # it is root
		{
			$src_array = $src_array.$engsen->[$src]->{'pos'}."&_";
			$mapping{ $src } = $engsen->[$src]->{'pos'}."&";
		}
		else
		{
			$src_array = $src_array.$engsen->[$src]->{'pos'}."~".$i."_";
			$mapping{ $src } = $engsen->[$src]->{'pos'}."~".$i;

			$i++;
		}
	}

	my $tgt_array = "";
	$i = 0;
	my($minmaxTable);
	foreach $src (sort {$minPos->{$a}<=>$minPos->{$b}} keys %$minPos)
	{
		$minmaxTable->[$i]->{'src'} = $src;
		$minmaxTable->[$i]->{'minPos'} = $minPos->{$src};
		$minmaxTable->[$i]->{'maxPos'} = $maxPos->{$src};

#	print "$i) $src $minPos->{$src} $maxPos->{$src}\n";

		$i++;
	}

	my($j);
	for($i=0;$i<@$minmaxTable;$i++) 
	{
		$combined = "";
		for($j=$i+1;$j<@$minmaxTable;$j++) 
		{

			my($src1,$src2);
			$src1 = $minmaxTable->[$i]->{'src'};
			$src2 = $minmaxTable->[$j]->{'src'};

			# Compare with $i and $j
			if($minmaxTable->[$j]->{'minPos'}>$minmaxTable->[$i]->{'maxPos'}) 
			{
				$j--;
				last;
			}
			elsif($minmaxTable->[$i]->{'minPos'}==$minmaxTable->[$j]->{'minPos'} && $minmaxTable->[$i]->{'maxPos'}==$minmaxTable->[$j]->{'maxPos'}) {
				if($combined eq "")
				{
						
					if($mapping{$src1} le $mapping{$src2}) {
						$combined.=$mapping{$src1}."-".$mapping{$src2};
					}
					else {
						$combined.=$mapping{$src2}."-".$mapping{$src1};
					}
				}
				else
				{
					$combined.="-".$mapping{$src2};

					@parts = split(/-/,$combined);
					$combined="";
					foreach $onepart (sort @parts) {
						$combined.="-".$onepart;
					}
					$combined=~s/^-//g;
				}
			}
			elsif($minmaxTable->[$j]->{'maxPos'}<=$minmaxTable->[$i]->{'minPos'}) 
			{
#	print $minmaxTable->[$j]->{'maxPos'}." --> ".$minmaxTable->[$i]->{'minPos'}."\n";
				if($combined eq "")
				{
					$combined.=$mapping{$src1}."<<".$mapping{$src2};
				}
				else
				{
					$combined.="<<".$mapping{$src2};
				}
			}
			else {
				if($combined eq "")
				{
					$combined.=$mapping{$src1}."<".$mapping{$src2};
				}
				else
				{
					$combined.="<".$mapping{$src2};
				}
			}
		}

		if($combined) {
			$tgt_array.=$combined."_";
			$i = $j;
		}
		else 
		{
			my($src) = $minmaxTable->[$i]->{'src'};
			$tgt_array.=$mapping{$src}."_";
		}
	}
	
#-----------------------------------------------------------------------------


	%hash_name = ();
	%hash_tgt = ();
	$hash_name{ $sword } = 0;
	
	$count = -1;
	for($var = $sword-1; $var >= 0; $var--)
	{
		if($srcwords{ $var } == 1)
		{
			$hash_name{ $var } = $count;
			$count--;
		}
	}
	$count = 1;
	for($var = $sword+1; $var < @$engsen; $var++)
	{
		if($srcwords{ $var } == 1)
		{
			$hash_name{ $var } = $count;
			$count++;
		}
	}

	%flags = ();
	foreach $src (sort {$a<=>$b} keys %srcwords)
	{
		my $tgt_min = 10000;
		my $tgt_max = -1;
		$flag = 0;
		foreach $tgt (@{$Align->{'aln'}->[$src]})
		{
			if($tgt eq "X")
			{
				$flag = 1;
				last;
			}
			else
			{
				if($tgt_min > $tgt)
				{
					$tgt_min = $tgt;
				}
				if($tgt_max < $tgt)
				{
					$tgt_max = $tgt;
				}
			}
		}
		if($flag == 0)
		{
			$flags{$src} = 1;
			$hash_tgt{ $src } = $tgt_min;
		}
	}

	%hash_tgt_map = ();
	$hash_tgt_map {$sword} = 0;
	$count = 1;
	foreach $tgt (sort { $hash_tgt{$a}<=>$hash_tgt{$b} } keys %hash_tgt)
	{
		if($hash_tgt{ $sword } <  $hash_tgt { $tgt }  and ($tgt ne $sword))
		{
			$hash_tgt_map{$tgt} = $count;
			$count++;
		}
	}
	$count = -1;
	foreach $tgt (sort { $hash_tgt{$b}<=>$hash_tgt{$a} } keys %hash_tgt)
	{
		if($hash_tgt{ $sword } > $hash_tgt { $tgt} and ($tgt ne $sword))
		{
			$hash_tgt_map{$tgt} = $count;
			$count--;
		}
	}
	
	foreach $src (sort {$a<=>$b} keys %srcwords)
	{
		if($flags{$src} == 1)
		{
			my($synfeat) = "";

			if($engsen->[$sword]->{'pos'} eq "")
			{
				$engsen->[$sword]->{'pos'} = "DUMMY";
#				my($nengwords) = $#{$engsen}+1;
#				print STDERR "Karthik".$engsen->[$sword]->{'word'}."  ".$nengwords."   ".$sword."\n\n\n";
			}
			if($hash_tgt{$src} == 10000 or $hash_tgt_map{$src} eq "")
			{
#				print $src."-->".$engsen->[$sword]->{'pos'}."-".$engsen->[$src]->{'pos'}.$hash_name{$src}."_D"."\n";
				$synfeat = $engsen->[$sword]->{'pos'}."-".$engsen->[$src]->{'pos'}.$hash_name{$src}."_D";
				$featuresSet{"$synfeat"} = 1 if(&checkCompat($purpose,"RELPOS"));
			}
			elsif($src!=$sword) 
			{
#				print $src."-->".$engsen->[$sword]->{'pos'}."-".$engsen->[$src]->{'pos'}.$hash_name{$src}."_".$hash_tgt_map{$src}."\n";
				$synfeat = $engsen->[$sword]->{'pos'}."-".$engsen->[$src]->{'pos'}.$hash_name{$src}."_".$hash_tgt_map{$src};
				$featuresSet{"$synfeat"} = 1 if(&checkCompat($purpose,"RELPOS"));
			}
		}
	}
#	print "\n------------------------------------------\n";
	

#-----------------------------------------------------------------------------

	my $divergence = "";

#	print "SenID is $sword  \n";
# print "Source Array $src_array x Target Array $tgt_array\n";


	if($src_array ne "")
	{
		chop($src_array);
		chop($tgt_array);
		$divergence = $src_array."==>".$tgt_array;
		$featuresSet{"$divergence"} = 1 if(&checkCompat($purpose,"REORDER"));
	}
	$newtime = time();

	#print "$sword ",$divergence," ",eval($newtime-$time)," ",$newtime,"\n";
	<<'#';
	print STDERR "$sword ";
	foreach $src (sort {$a<=>$b} keys %srcwords)
	{
		print STDERR $engsen->[$src]->{'pos'}," ";
	}
	print STDERR "\n";
#

	foreach $key (keys %featuresSet) {
		$this->{$key} = $featuresSet{$key};
	}
	return $this;
}

sub addSpanNodeFeats {
	my($this) = shift;
	my($leftPos,$rightPos,$srcNodes,$tgtNodes) = @_;
	if($leftPos==200 || $rightPos==-1) {
		return 0;
	}
	if($tgtNodes==0) {
		return 0;
	}
	my($span) = $rightPos-$leftPos+1;
	$this->{'spanSrc'} = $span/$srcNodes;
	$this->{'spanTgt'} = $span/$tgtNodes;
}

sub getnodeSynFeatures {
	my($this) = shift;
	my($sword) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($Dep) = shift;
	my($Align)= shift;
	my($purpose) = shift;

	my(%featuresSet);

	my %srcwords = ();
	$srcwords{ $sword } = 1;
	foreach $child (@{$Dep->[$sword]->{'attch'}}) 
	{
		$srcwords{ $child } = 1;
	}

	#print "Getting divergence for node $sword\n";
	my($time) = time() ;

	my $src_array = "";
	my %tgtwords = ();
	my %mapping = ();
	my $src;
	my $i = 1;
	my ($minPos);
	my ($maxPos);

	foreach $src (sort {$a<=>$b} keys %srcwords)
	{
		my $tgt_min = 10000;  
		my $tgt_max = -1;  
		foreach $tgt (@{$Align->{'aln'}->[$src]})
		{
			if($tgt_min > $tgt)
			{
				$tgt_min = $tgt;
			}
			if($tgt_max < $tgt)
			{
				$tgt_max = $tgt;
			}
		}
		$minPos->{$src} = $tgt_min;
		$maxPos->{$src} = $tgt_max;
	}

	%mapping = ();
	foreach $src (sort {$a<=>$b} keys %srcwords)
	{
		if( $src  == $sword) # it is root
		{
			$src_array = $src_array.$engsen->[$src]->{'pos'}."&_";
			$mapping{ $src } = $engsen->[$src]->{'pos'}."&";
		}
		else
		{
			$src_array = $src_array.$engsen->[$src]->{'pos'}."~".$i."_";
			$mapping{ $src } = $engsen->[$src]->{'pos'}."~".$i;

			$i++;
		}
	}

	my $tgt_array = "";
	$i = 0;
	my($minmaxTable);
	foreach $src (sort {$minPos->{$a}<=>$minPos->{$b}} keys %$minPos)
	{
		$minmaxTable->[$i]->{'src'} = $src;
		$minmaxTable->[$i]->{'minPos'} = $minPos->{$src};
		$minmaxTable->[$i]->{'maxPos'} = $maxPos->{$src};

#	print "$i) $src $minPos->{$src} $maxPos->{$src}\n";

		$i++;
	}

	my($j);
	for($i=0;$i<@$minmaxTable;$i++) 
	{
		$combined = "";
		for($j=$i+1;$j<@$minmaxTable;$j++) 
		{

			my($src1,$src2);
			$src1 = $minmaxTable->[$i]->{'src'};
			$src2 = $minmaxTable->[$j]->{'src'};

			# Compare with $i and $j
			if($minmaxTable->[$j]->{'minPos'}>$minmaxTable->[$i]->{'maxPos'}) 
			{
				$j--;
				last;
			}
			elsif($minmaxTable->[$i]->{'minPos'}==$minmaxTable->[$j]->{'minPos'} && $minmaxTable->[$i]->{'maxPos'}==$minmaxTable->[$j]->{'maxPos'}) {
				if($combined eq "")
				{
						
					if($mapping{$src1} le $mapping{$src2}) {
						$combined.=$mapping{$src1}."-".$mapping{$src2};
					}
					else {
						$combined.=$mapping{$src2}."-".$mapping{$src1};
					}
				}
				else
				{
					$combined.="-".$mapping{$src2};

					@parts = split(/-/,$combined);
					$combined="";
					foreach $onepart (sort @parts) {
						$combined.="-".$onepart;
					}
					$combined=~s/^-//g;
				}
			}
			elsif($minmaxTable->[$j]->{'maxPos'}<=$minmaxTable->[$i]->{'minPos'}) 
			{
#	print $minmaxTable->[$j]->{'maxPos'}." --> ".$minmaxTable->[$i]->{'minPos'}."\n";
				if($combined eq "")
				{
					$combined.=$mapping{$src1}."<<".$mapping{$src2};
				}
				else
				{
					$combined.="<<".$mapping{$src2};
				}
			}
			else {
				if($combined eq "")
				{
					$combined.=$mapping{$src1}."<".$mapping{$src2};
				}
				else
				{
					$combined.="<".$mapping{$src2};
				}
			}
		}

		if($combined) {
			$tgt_array.=$combined."_";
			$i = $j;
		}
		else 
		{
			my($src) = $minmaxTable->[$i]->{'src'};
			$tgt_array.=$mapping{$src}."_";
		}
	}
	
#-----------------------------------------------------------------------------


	%hash_name = ();
	%hash_tgt = ();
	$hash_name{ $sword } = 0;
	
	$count = -1;
	for($var = $sword-1; $var >= 0; $var--)
	{
		if($srcwords{ $var } == 1)
		{
			$hash_name{ $var } = $count;
			$count--;
		}
	}
	$count = 1;
	for($var = $sword+1; $var < @$engsen; $var++)
	{
		if($srcwords{ $var } == 1)
		{
			$hash_name{ $var } = $count;
			$count++;
		}
	}

	%flags = ();
	foreach $src (sort {$a<=>$b} keys %srcwords)
	{
		my $tgt_min = 10000;
		my $tgt_max = -1;
		$flag = 0;
		foreach $tgt (@{$Align->{'aln'}->[$src]})
		{
			if($tgt eq "X")
			{
				$flag = 1;
				last;
			}
			else
			{
				if($tgt_min > $tgt)
				{
					$tgt_min = $tgt;
				}
				if($tgt_max < $tgt)
				{
					$tgt_max = $tgt;
				}
			}
		}
		if($flag == 0)
		{
			$flags{$src} = 1;
			$hash_tgt{ $src } = $tgt_min;
		}
	}

	%hash_tgt_map = ();
	$hash_tgt_map {$sword} = 0;
	$count = 1;
	foreach $tgt (sort { $hash_tgt{$a}<=>$hash_tgt{$b} } keys %hash_tgt)
	{
		if($hash_tgt{ $sword } <  $hash_tgt { $tgt }  and ($tgt ne $sword))
		{
			$hash_tgt_map{$tgt} = $count;
			$count++;
		}
	}
	$count = -1;
	foreach $tgt (sort { $hash_tgt{$b}<=>$hash_tgt{$a} } keys %hash_tgt)
	{
		if($hash_tgt{ $sword } > $hash_tgt { $tgt} and ($tgt ne $sword))
		{
			$hash_tgt_map{$tgt} = $count;
			$count--;
		}
	}
	
	foreach $src (sort {$a<=>$b} keys %srcwords)
	{
		if($flags{$src} == 1)
		{
			my($synfeat) = "";

			if($engsen->[$sword]->{'pos'} eq "")
			{
				$engsen->[$sword]->{'pos'} = "DUMMY";
#				my($nengwords) = $#{$engsen}+1;
#				print STDERR "Karthik".$engsen->[$sword]->{'word'}."  ".$nengwords."   ".$sword."\n\n\n";
			}
			if($hash_tgt{$src} == 10000 or $hash_tgt_map{$src} eq "")
			{
#				print $src."-->".$engsen->[$sword]->{'pos'}."-".$engsen->[$src]->{'pos'}.$hash_name{$src}."_D"."\n";
				$synfeat = $engsen->[$sword]->{'pos'}."-".$engsen->[$src]->{'pos'}.$hash_name{$src}."_D";
				$featuresSet{"$synfeat"} = 1 if(&checkCompat($purpose,"RELPOS"));
			}
			elsif($src!=$sword) 
			{
#				print $src."-->".$engsen->[$sword]->{'pos'}."-".$engsen->[$src]->{'pos'}.$hash_name{$src}."_".$hash_tgt_map{$src}."\n";
				$synfeat = $engsen->[$sword]->{'pos'}."-".$engsen->[$src]->{'pos'}.$hash_name{$src}."_".$hash_tgt_map{$src};
				$featuresSet{"$synfeat"} = 1 if(&checkCompat($purpose,"RELPOS"));
			}
		}
	}
#	print "\n------------------------------------------\n";
	

#-----------------------------------------------------------------------------

	my $divergence = "";

#	print "SenID is $sword  \n";
# print "Source Array $src_array x Target Array $tgt_array\n";


	if($src_array ne "")
	{
		chop($src_array);
		chop($tgt_array);
		$divergence = $src_array."==>".$tgt_array;
		$featuresSet{"$divergence"} = 1 if(&checkCompat($purpose,"REORDER"));
	}
	$newtime = time();

	#print "$sword ",$divergence," ",eval($newtime-$time)," ",$newtime,"\n";
	<<'#';
	print STDERR "$sword ";
	foreach $src (sort {$a<=>$b} keys %srcwords)
	{
		print STDERR $engsen->[$src]->{'pos'}," ";
	}
	print STDERR "\n";
#

	foreach $key (keys %featuresSet) {
		$this->{$key} = $featuresSet{$key};
	}
	return $this;
}

sub getnodeGFeatures {
	
	my($this) = shift;
	my($sword) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($Dep) = shift;
	my($Align)= shift;
	my $purpose = shift;

	my($i);
	my($nengwords);
	my(%featuresSet);
#	print $Dep->[1]->{'attch'}[0],"kstyji\n";

	my %src_hash = ();


#	print "\nkarthik $Dep",$Dep->[0]->{'root'},"\n";
	
	&getnodessubtree($sword,$engsen,$hinsen,$Dep,$Align,\%src_hash);
<< '#';
	print "here $sword:";
	foreach $src ((sort {$a<=>$b} keys %src_hash))
	{
		print $src," ";
	}
	print "\n";

#
	if(&checkCompat($purpose,"COHESION")) {
		my $tgt_low = 10000;
		my $tgt_high = -1;
		my $src_low = 10000;
		my $src_high = -1;


		my $src;
		my %tgt_all = ();
		foreach $src ((sort {$a<=>$b} keys %src_hash))
		{
			if($src_low > $src)
			{
				$src_low = $src;
			}
			if($src_high < $src)
			{
				$src_high = $src;
			}
			foreach $tgt (@{$Align->{'aln'}->[$src]})
			{
				$tgt_all{ $tgt } = 1;
#			print $tgt,",";
				if($tgt_low > $tgt)
				{
					$tgt_low = $tgt;
				}
				if($tgt_high < $tgt)
				{
					$tgt_high = $tgt;
				}	
			}
#		print " ";
		}
#		print "\n";

		my $tgt_count = scalar(keys %tgt_all);
		my $srcdiff = $src_high - $src_low + 1;
		my $tgtdiff = $tgt_high - $tgt_low + 1;

		my $cohesion;

		if($tgt_count != 0)
		{
#	$span = $tgtdiff / $tgt_count;
			$cohesion = $tgt_count / $tgtdiff;
			$featuresSet{"cohesion"} = $cohesion;
		}

	}


#	print  $cohesion,"|",$tgtdiff,"|",$tgt_count,"\n";

#	print "Overlap Feature of $sword(".join('_',keys %src_hash).")\n";
	if(&checkCompat($purpose,"OVERLAP")) {

		my %numberpos = ();
		my $nengwords=$#$engsen+1;
		my $nhinwords=$#$hinsen+1;
		my $total = 0;
		my $nonnulls = 0;
		my $overlap = 0;

		foreach $src ((sort {$a<=>$b} keys %src_hash))
		{
#			print "\tAlign of $src :";
			my $tgt;
			foreach $tgt (@{$Align->{'aln'}->[$src]}) 
			{
#				print $tgt,",";
				$numberpos{$tgt}++;
			}
		}

#		print "\n";
		foreach $npos (keys %numberpos)
		{
			if($numberpos{$npos}>1)
			{ 
				$overlap+=$numberpos{$npos}*$numberpos{$npos}; 
			}
#			print "\tTarget POS:";
#			print $npos,"($numberpos{$npos}) -->",$overlap,"\n";

			$nonnulls++;

			$total+= $numberpos{$npos};
		}

#		print $engsen->[$sword]->{'word'},"\n";
		if($total)
		{ 
			$this->{'nulls'} = ($nhinwords-$nonnulls)/$nhinwords;
			$this->{'overlap'} = $overlap/$total;

#			print "Final Overlap = $this->{'overlap'}\n";
		}

	}

	if(&checkCompat($purpose,"ROOTPOS")) {
		my($rootpos,$roothinpos);
		my $nengwords=$#$engsen;
		my $nhinwords=$#$hinsen;

		$rootpos = $Dep->[0]->{'root'};
		if($Align->{'aln'}->[$rootpos])
		{ 
			$this->{"rootpos"} = $Align->{'aln'}->[$rootpos]/$nhinwords; 
		}
	}

	foreach $key (keys %featuresSet) 
	{
		$this->{$key} = $featuresSet{$key};
	}

	return $this;
}

sub getnodessubtree {
	my($sword) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($Dep) = shift;
	my($Align)= shift;
	my($src_hash) = shift;
	
	foreach $child  (@{$Dep->[$sword]->{'attch'}})
	{
#		print $child,"\n";
		$src_hash->{ $child } = 1;
		&getnodessubtree($child,$engsen,$hinsen,$Dep,$Align,$src_hash);
	}
	$src_hash->{ $sword } = 1;


}

sub getnodeLTransFeats {

	my($this) = shift;
	my($snode) = shift;
	my($tnode) = shift;

	my($engsen) = shift;

	my($SDep) = shift;
	my($TDep) = shift;

	my($children) = shift;
	my($purpose) = shift;

	my($numHin) = $#$hinsen;

	my(%featuresSet) = ();

	(@snodes) = split(/\s+/,$snode);

	$snode=~/l0~([0-9]+)/;
	$sword = $1;

	my($parentSword) = $SDep->[$sword]->{'parent'};
	my($srcParent)="l0~".$engsen->[$parentSword]->{'root'}."~".$engsen->[$parentSword]->{'pos'};
	my($srcNodeFeat)="";

	my $src;
	my $tgt;
	foreach $node (@snodes)
	{
		$node=~/(l[0-9]+~)([0-9]+)/;
		my $l = $1;
		my $n = $2;
		$src.=$l.$engsen->[$n]->{'root'}."~".$engsen->[$n]->{'pos'}."___";
		if($node=~/l0~/) {
			$srcNodeFeat = $l.$engsen->[$n]->{'root'}."~".$engsen->[$n]->{'pos'};
		}
		else {
			$srcNodeFeat.= "___".$l.$engsen->[$n]->{'pos'};
		}
	}
	$src=~s/___$//g;

	my(@srcChildren) = ();
	
	$tgt = $TDep->[$tnode]->{'rt'};
	@twords = split(/_/,$tgt);

	foreach $child (@{$TDep->[$tnode]->{'attch'}}) {
		my($srcChildNode) = $TDep->[$child]->{'srcNode'};
		@sChildNodes = split(/\s+/,$srcChildNode);
		
		my($srcChild);
		foreach $node (@sChildNodes) {
	               $node=~/(l[0-9]+~)([0-9]+)/;
 	               $srcChild.=$1.$engsen->[$2]->{'root'}."~".$engsen->[$2]->{'pos'}."___";
		}
		$srcChild=~s/___$//g;
		push(@srcChildren,$srcChild);
		#print STDERR "$child : $srcChild\n";
	}

	$srcsin = $engsen->[$sword]->{'root'};
	$tgtsin = $TDep->[$tnode]->{'rt'};

	$src_gnp = $engsen->[$sword]->{'gnp'};
	$tgt_gnp = $TDep->[$tnode]->{'gnp'};

	$src_tense = $engsen->[$sword]->{'tense'};
	$src_tense = "NULL" if(!$src_tense);
	$tgt_tense = $TDep->[$tnode]->{'tense'};
	$tgt_tense = "NULL" if(!$tgt_tense);

	$srcParentTense = $engsen->[$parentSword]->{'tense'};
	$srcParentTense = "NULL" if(!$srcParentTense);

	$src_vib = $SDep->[$sword]->{'role'};
	if(!$src_vib) {
		$src_vib="ROOT";
	}
	$tgt_vib = $TDep->[$tnode]->{'vib'};

	my($numSrc) = scalar(@snodes);
	my($numTgt) = scalar(@twords);

#	$featuresSet{$srcNodeFeat} = 1;
	
#	Atomic Treelets 
	if (&checkCompat($purpose,"ATOMICTREELETS")) 
	{
		$key = $src."____".$tgt;

		#print STDERR "The is Key: ($src-$tgt)".$key."\n";
		$prob = $dbs{'cacheAtomictreelet'}->{"$key"};
		if(!($prob))
		{ 
			$prob = $dbs{'Atomictreelet'}->{"$key"};
			if($prob)
			{ 
				$dbs{'cacheAtomictreelet'}->{"$key"} = $prob; 
			}
		}
		#print STDERR  "Prob : ".$prob."\n";
		$featuresSet{"atomictreelet"} = $prob**(1/($numSrc*$numTgt)) if($src && $tgt);# if($prob);
		$featuresSet{"atomictreelet2"} = $prob if($src && $tgt);# if($prob);
	}
	if (&checkCompat($purpose,"DICETREELETS")) 
	{
		$key = $src."____".$tgt;
#		print STDERR "*The key is DICETREELET ".$key."\n";
		$prob = $dbs{'cacheDiceRootProb'}->{"$key"};
		if(!($prob))
		{ 
			$prob = $dbs{'diceRootProb'}->{"$key"};
			if($prob)
			{ 
				$dbs{'cacheDiceRootProb'}->{"$key"} = $prob; 
			}
		}
		$featuresSet{"diceRootProb"} = $prob if($src && $tgt);# if($prob);
#		print STDERR "The key is DICETREELET ".$key."  and prob is $prob\n";
	}
	if (&checkCompat($purpose,"DICETREELETSPARENT")) 
	{
		$key = $srcParent."____".$tgt;
#		print STDERR "The key is DICETREELETPARENT ".$key."\n";
		$prob = $dbs{'cacheDiceRootProb'}->{"$key"};
		if(!($prob))
		{ 
			$prob = $dbs{'diceRootProb'}->{"$key"};
			if($prob)
			{ 
				$dbs{'cacheDiceRootProb'}->{"$key"} = $prob; 
			}
		}
		$featuresSet{"diceRootProbParent"} = $prob if($srcParent && $tgt);# if($prob);
#		print STDERR "The key is DICETREELETPARENT ".$key."  and prob is $prob\n";
	}

	if (&checkCompat($purpose,"DICETREELETSCHILDREN")) 
	{
		$totalProb = 0;
		foreach $srcChild (@srcChildren) {
			$key = $srcChild."____".$tgt;
			#print STDERR "The key is DICETREELETCHILD ".$key."\n";
			$prob = $dbs{'cacheDiceRootProb'}->{"$key"};
			if(!($prob))
			{ 
				$prob = $dbs{'diceRootProb'}->{"$key"};
				if($prob)
				{ 
					$dbs{'cacheDiceRootProb'}->{"$key"} = $prob; 
				}
			}
			$totalProb+=$prob;
		}

		$featuresSet{"diceRootProbChildren"} = $totalProb/scalar(@srcChildren) if(@srcChildren>0 && $tgt);# if($prob);
		#	print STDERR "The key is DICETREELETCHILDREN ".$key."  and prob is $totalProb\n";
	}

	if (&checkCompat($purpose,"GNP")) 
	{
		$key = $src_gnp."___".$tgt_gnp;
		$prob = $dbs{'cachegnpProb'}->{"$key"};
		if(!($prob))
		{ 
			$prob = $dbs{'gnpProb'}->{"$key"};
			if($prob)
			{ 
				$dbs{'cachegnpProb'}->{"$key"} = $prob; 
			}
		}
#		print STDERR  "Prob : ".$prob."\n";
#		$featuresSet{"gnp"} = $prob if($prob);
		$featuresSet{"gnp:"."$key"} = 1 if($src_gnp && $tgt_gnp);# if($prob);
#		print STDERR "Karthik GNP:".$key."  -->  ".$prob."\n";
	}
	
	if (&checkCompat($purpose,"TENSE")) 
	{
		$key = $src_tense."___".$tgt_tense;
		$prob = $dbs{'cachetenseProb'}->{"$key"};
		if(!($prob))
		{ 
			$prob = $dbs{'tenseProb'}->{"$key"};
			if($prob)
			{ 
				$dbs{'cachetenseProb'}->{"$key"} = $prob; 
			}
		}
	#	print STDERR  "Prob : ".$prob."\n";
		$featuresSet{"tense:"."$key"} = 1 if($src_tense && $tgt_tense); # if($prob);
#		$featuresSet{"tense"} = $prob if($prob);
#		print STDERR "Karthik TENSE:".$key."  -->  ".$prob."\n";
	}
	if (&checkCompat($purpose,"VIB")) 
	{
		$key = $src_vib."___".$tgt_vib;
		$featuresSet{"roleVib:"."$key"} = 1 if($src_vib && $tgt_vib); # if($prob);
	}

	if (&checkCompat($purpose,"VIBTENSE")) 
	{
		$key = $src_vib."+".$srcParentTense."___".$tgt_vib;
		$featuresSet{"roleTenseVib:"."$key"} = 1 if($src_vib && $srcParentTense && $tgt_vib); # if($prob);

	}

#	print STDERR "THE treelets   ".$snode."   -->  ".$tnode."\n";

#	print STDERR "$snode($engsen->[$sword]->{'root'}) == In Local Features==> $tnode($TDep->[$tnode]->{'rt'}) [";
#	foreach my $child (@{$TDep->[$tnode]->{'attch'}}) {
#		print STDERR "$child,";
#	}
#	print STDERR "]\n";

# Correspondence through Dice Coefficient
#	if (($fert==1) && &checkCompat($purpose,"DICECOEFF")) {
#	if (&checkCompat($purpose,"DICECOEFF")) {
#		$DiceWord = $dbs{'cacheDicewd'}->{"$srcword $tgtphr"};
#		if(!($DiceWord))
#		{ 
#			$DiceWord = $dbs{'Dicewd'}->{"$srcword $tgtphr"};
#			if($DiceWord)
#			{ $dbs{'cacheDicewd'}->{"$srcword $tgtphr"} = $DiceWord; }
#		}
#		$featuresSet{"diceword"} = $DiceWord if($DiceWord);
#	}

	
#	if (&checkCompat($purpose,"ATOMICTREELETS")) 
#	{
#		$key = $src."___".$tgt;
#	#	print STDERR "Key: ".$key."\n";
#		$prob = $dbs{'cacheAtomictreelet'}->{"$key"};
#		if(!($prob))
#		{ 
#			$prob = $dbs{'Atomictreelet'}->{"$key"};
#			if($prob)
#			{ 
#				$dbs{'cacheAtomictreelet'}->{"$key"} = $prob; 
#			}
#		}
#	#	print STDERR  "Prob : ".$prob."\n";
#		$featuresSet{"atomictreelet"} = $prob if($prob);
#
#	}

#	print STDERR "---------------\n";
	foreach $feat (keys %featuresSet) {
#		print STDERR " Local Feat = $feat $featuresSet{$feat}\n";
		$this->{$feat} = $featuresSet{$feat};
	}
#	print STDERR "---------------\n\n";

	return;

}
sub getnodeLMTransFeats {

	my($this) = shift;
	my($snode) = shift;
	my($tnode) = shift;

	my($engsen) = shift;

	my($SDep) = shift;
	my($TDep) = shift;

	my($children) = shift;
	my($purpose) = shift;

	my($numHin) = $#$hinsen;

	my(%featuresSet) = ();
	#my $lm = "/home1/sriram/Vaanee/subtreeLM/corpus12300.train.hn.lm";
	#my $lm = "/home1/sriram/Vaanee/subtreeLM/sentences.lm";
	my $lm = $C{'lmFile'}; #CHANGE MAY 27, 2010

	$snode=~/l0~([0-9]+)/;
	$sword = $1;

#	print STDERR "Karthik:Tnode is $tnode \n";	
	my (@snodes) = split(/\s+/,$snode);
	my (@tnodes) = split(/\s+/,$tnode);
	
	$tword = $tnodes[0];

	my $src;
	my $tgt;
	foreach $node (@snodes)
	{
		$node=~/(l[0-9]+~)([0-9]+)/;
		$word =  $engsen->[$2]->{'root'};
		$src.=$1.$word." ";
	}
	chop($src);
	foreach $node (@tnodes)
	{
		$tgt = $tgt.$TDep->[$node]->{'rt'}."_";
	}
	chop($tgt);

#	my $string = $TDep->[$tword]->{'subTreeString'};
	my $string = $TDep->[$tword]->{'translation'};
	my $lString = $TDep->[$tword]->{'localTranslation'};

	if(! $string) {
		return;
	}

#	my @words = split(/___/,$string);
#	my($wordString);
#	foreach $word (@words) {
#		print $word."\n";
#		$word=~s/[^\[]+\[(.*?)\]/$1/;
#		print $word."\n";
#		my($w,$p,$t,$g) = split(/\+/,$word);
#		$w=~s/---/ /g;
#		$wordString.=$w." ";
#	}
#	$wordString=~s/\s+$//g;

#	$pos = $TDep->[$tword]->{'srcPos'};
#	$posLM = "$DATA/hindi/LMs/syntaxWordSubTree/$pos.lm";
#	$wordSubTreePerx = &getLMScore($posLM,"WordSubTree",$wordString);

	$string=~s/INS/ /g;	$lString=~s/INS/ /g;
	$string=~s/NULL/ /g;	$lString=~s/NULL/ /g;
	$string=~s/\s+/ /g;	$lString=~s/\s+/ /g;
	$string=~s/^\s+//g;	$lString=~s/^\s+//g;
	$string=~s/\s+$//g;	$lString=~s/\s+$//g;
	my @words = split(/\s+/,$string);
	$wordSubTreePerx = &getLMScore($lm,"WordSubTree",$string);
#	print STDERR "Feature $string $wordSubTreePerx\n";

	if(@{$TDep->[$tword]->{'attch'}}>=1) {
		$featuresSet{"wordSubTreeLM"} = $wordSubTreePerx if($wordSubTreePerx && $string ne $lString);
		#$featuresSet{"wordSubTreeLM"} = $wordSubTreePerx if($wordSubTreePerx);
	}
#	$featuresSet{"wordSubTreeLM-1"} = $wordSubTreePerx if($wordSubTreePerx && @words>1);
#	$featuresSet{"wordSubTreeLM-4"} = $wordSubTreePerx if($wordSubTreePerx && @words>4);
#	$featuresSet{"LM_for ".$wordString} = 1;
#	print STDERR "Karthik string is $string and word is $tword pos is $pos perx is $perx \n";

#	------------------------

	foreach $feat (keys %featuresSet) {
#		print STDERR " Local Feat = $feat $featuresSet{$feat}\n";
		$this->{$feat} = $featuresSet{$feat};
	}
	#print "\n\n";
	
	return;

}

sub LMandCache {

	my($pos) = $_[0];
	my($lmType) = $_[1];
	my($stringsRef) = $_[2];
	my($i);

	if(!&checkCompat("u","LM")) {
		return;
	}

#	$lm = "/home1/sriram/data/tourismCorpus/hindi/LMs/syntaxWordSubTree/".$pos.".lm";
#	$lm = "/home1/sriram/Vaanee/subtreeLM/sentences.lm";
	$lm = $C{'lmFile'}; #CHANGE MAY 27, 2010
	#$lm = "/home1/sriram/Vaanee/subtreeLM/corpus12300.train.hn.lm";

	open(FILE,">/tmp/strings.$$.tmp");
#	print STDERR "Hello I am here printing strings.tmp $lm\n";

	my($string,@wordStrings);
	foreach $string (@$stringsRef) {
		my($wordString);
#		my @words = split(/___/,$string);
#		foreach $word (@words) {
#			$word=~s/[^\[]+\[(.*?)\]/$1/;
#			my($w,$p,$t,$g) = split(/\+/,$word);
#			$w=~s/---/ /g;
#			$wordString.=$w." ";
#		}
#		$wordString=~s/\s+$//g;
#		$wordString=~s/INS/ /g;
#		$wordString=~s/NULL/ /g;
#		$wordString=~s/\s+/ /g;

		$string=~s/INS/ /g;
		$string=~s/NULL/ /g;
		$string=~s/\s+/ /g;
		$string=~s/^\s+//g;
		$string=~s/\s+$//g;
		$wordString = $string;

		$perx = $dbs{"cache".$lmType}->{"$wordString"};
		if(! $perx) {
			print FILE $wordString."\n";
			push(@wordStrings,$wordString);
		}
#		print STDERR "Perx1 = $wordString $perx\n";
	}
	close(FILE);

	if(@wordStrings) {
	system("ngram -ppl /tmp/strings.$$.tmp -lm $lm -debug 1 > /tmp/score_gram.$$.tmp 2> /tmp/score_gram.$$.err");

	open(LMscores1,"/tmp/score_gram.$$.tmp");
	my @LMlines1 = <LMscores1>;
	close(LMscores1);

	for($i=0;$i<@wordStrings;$i++) {
	#for($i=0;$i<@LMlines1-2;$i++) {

		$numWords = scalar(split(/\s+/,$wordStrings[$i]));

		(@items1) = split(/\s+/,$LMlines1[$i*4+2]);
		$perx = $items1[5];
		$perx = $perx**(1/($numWords)) if($numWords);

		$dbs{"cache".$lmType}->{"$wordStrings[$i]"} = $perx;
		#print STDERR "Perx2 = ".$wordStrings[$i]." ".$perx."\n";
	}
	}
}


sub getLMScore {
	my($lm) = $_[0];
	my($lmType) = $_[1];
	my($string) = $_[2];


	$perx = $dbs{"cache".$lmType}->{"$string"};
	if($perx) {
		return $perx;
	}
	else {
		open(FILE,">/tmp/string.$$.tmp");
		print FILE $string."\n";
		close(FILE);

		$numWords = scalar(split(/\s+/,$string));

		system("ngram -ppl /tmp/string.$$.tmp -lm $lm -debug 1 > /tmp/score_gram.$$.tmp 2> /tmp/score_gram.$$.err");

		open(LMscores1,"/tmp/score_gram.$$.tmp");
		my @LMlines1 = <LMscores1>;
		my $LMnum1 = @LMlines1;
		close(LMscores1);

		(@items1) = split(/\s+/,$LMlines1[2]);
		$perx = $items1[5];

		$perx = $perx**(1/($numWords)) if($numWords);

		$dbs{"cache".$lmType}->{"$string"} = $perx;

		return $perx;
	}	

}





sub getnodeSynTransFeats {

	my($this) = shift;
	my($snode) = shift;
	my($tnode) = shift;

	my($engsen) = shift;

	my($SDep) = shift;
	my($TDep) = shift;

	my($children) = shift;
	my($purpose) = shift;

	my($numHin) = $#$hinsen;

	my(%featuresSet) = ();

	$snode=~/l0~([0-9]+)/;
	$sword = $1;
	
	my (@snodes) = split(/\s+/,$snode);
	my (@tnodes) = split(/\s+/,$tnode);
	
	$tword = $tnodes[0];

	my $src;
	my $tgt;
	foreach $node (@snodes)
	{
		$node=~/l[0-9]+~([0-9]+)/;
		$word =  $engsen->[$1]->{'root'};
		$node=~/(l[0-9]+~)([0-9]+)/;
		$node = $1.$word;
#		print STDERR $node." is the node\n";
		$src = $src. $node." ";
	}
	chop($src);
	foreach $node (@tnodes)
	{
		$tgt = $tgt.$TDep->[$node]->{'rt'}."_";
	}
	chop($tgt);


	$src_gnp = $engsen->[$sword]->{'gnp'};
	$tgt_gnp = $TDep->[$tword]->{'gnp'};

	$src_tense = $engsen->[$sword]->{'tense'};
	$tgt_tense = $TDep->[$tword]->{'tense'};

	$src_vib = $engsen->[$sword]->{'role'};
	$tgt_vib = $TDep->[$tword]->{'vib'};

	my(%relPositions);
	$relPositions{$TDep->[$tword]->{'srcPos'}} = 0;

	foreach my $child (@{$TDep->[$tword]->{'attch'}}) {
		$relPositions{$TDep->[$child]->{'srcRole'}} = $TDep->[$child]->{'relPos'};

		if($TDep->[$child]->{'relPos'}>0) {
			$featuresSet{"relPos:$TDep->[$tword]->{'srcPos'}-$TDep->[$child]->{'srcRole'}"} = 1;
		}
		else {
			$featuresSet{"relPos:$TDep->[$child]->{'srcRole'}-$TDep->[$tword]->{'srcPos'}"} = 1;
		}
	}

	if(scalar(keys %relPositions)>1) {
		my $string = "relOrder:";
		foreach my $element (sort {$relPositions{$a}<=>$relPositions{$b}} keys %relPositions) {
			$string.=$element."-" if($element ne "INSERT" && $element ne "PARENT");
		}
		$string=~s/-$//g;
		$featuresSet{"$string"} = 1;
	}


#	------------------------

	foreach $feat (keys %featuresSet) {
#		print STDERR " Local Feat = $feat $featuresSet{$feat}\n";
		$this->{$feat} = $featuresSet{$feat};
	}
	#print "\n\n";
	
	return;

}


sub getEntriesTable {
	my($dbkey) = shift;;
	my($key) = shift;

	my($completeValue) =  $dbs{$dbkey}->{$key};

	return split(/___/,$completeValue);
}

sub getnodeLFeaturesNew {

	my($this) = shift;
	my($snode) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($twordref) = shift;
	my($purpose) = shift;

	my($numHin) = $#$hinsen;

	my(%featuresSet) = ();

#if($LFeatureDb{"$FCONF\_$engsen\_$hinsen\_$sword\_$tword"}) {

#	%featuresSet = %{$LFeatureDb{"$FCONF\_$engsen\_$hinsen\_$sword\_$tword"}};
#	foreach $feat (keys %featuresSet) {
#		$this->{$feat} = $featuresSet{$feat};
#}
# 	print "Old Set : $FCONF\_$engsen\_$hinsen\_$sword\_$tword\n";
#	return;
#}

	$snode=~/l0~([0-9]+)/;
	$sword = $1;

	my($srcword,$srccat,$srcroot,$srcrole,$verbroot,$srcprep,$srcaux);
	my(@tgtwords,@tgtcats,@tgtroots,@tgtpreps,@tgtauxs);
	my($tgtphr,$tgtrootphr,$tgtcatphr,$tgtauxphr);
	my($prevsrccat,$nextsrccat,$srccatContext);
	my($prevtgtcat,$nexttgtcat,$tgtcatContext);

	$srcword = $engsen->[$sword]->{'word'};			
	$srcroot = $engsen->[$sword]->{'root'};			
	$srcroot = lc($srcroot);
	# Get srccat
	$srccat="";
	while($snode=~/l([0-9]+)~([0-9]+)/g) {
		$srccat.= "l$1~".$engsen->[$2]->{'pos'}."/".eval($2-$sword)."_";			
	}
	$srccat=~s/_$//g;

	$srcprep=lc($engsen->[$sword]->{'PREP'});
	$srcaux=lc($engsen->[$sword]->{'AUX'});

	$srccatContext = $engsen->[$sword]->{'pos'};
	$prevsrccat = $engsen->[$sword-1]->{'pos'} if($sword>0);
	$nextsrccat = $engsen->[$sword+1]->{'pos'} if($sword<=$#$engsen);
	$srccatContext = $prevsrccat."~".$srccatContext."~".$nextsrccat;

	
=cut
	my $srcpre4 = $engsen->[$sword]->{'prefix4'};
	my $srcpre3 = $engsen->[$sword]->{'prefix3'};
	my $srcpre2 = $engsen->[$sword]->{'prefix2'};
	my $srcpre1 = $engsen->[$sword]->{'prefix1'};

	my $srcsuf4 = $engsen->[$sword]->{'suffix4'};
	my $srcsuf3 = $engsen->[$sword]->{'suffix3'};
	my $srcsuf2 = $engsen->[$sword]->{'suffix2'};
	my $srcsuf1 = $engsen->[$sword]->{'suffix1'};
=cut


	
	my($mintword,$tword);
	if(@{$twordref}==0) {
# $featuresSet{"null"} = 1;
	}
	else {
		foreach $tword (sort {$a<=>$b} @{$twordref}) {
			push(@tgtwords,$hinsen->[$tword]->{'word'});
			push(@tgtroots,$hinsen->[$tword]->{'root'});
			push(@tgtcats,$hinsen->[$tword]->{'pos'});
			push(@tgtpreps,$hinsen->[$tword]->{'PREP'}) if($hinsen->[$tword]->{'PREP'} ne "");
			push(@tgtauxs,$hinsen->[$tword]->{'AUX'}) if($hinsen->[$tword]->{'AUX'} ne "");
		}
	}

	my($fert) = scalar(@tgtwords);

#	if($fert>2) { return; }

	$tgtphr=join('_',$tgtwords[0]);
	$tgtrootphr=join('_',$tgtroots[0]);
	$tgtcatphr=join('_',@tgtcats);
	$tgtprepphr=join(',',@tgtpreps);
	$tgtauxphr=join(',',@tgtauxs);


	foreach $tword (sort {$a<=>$b} @{$twordref}) {
		$tgtcatContext = $hinsen->[$tword]->{'pos'};
		$prevtgtcat = $hinsen->[$tword-1]->{'pos'} if($tword>0);
		$nexttgtcat = $hinsen->[$tword+1]->{'pos'} if($tword<$numHin);
		$tgtcatContext = $prevtgtcat."~".$tgtcatContext."~".$nexttgtcat;
	}

#	print "POS-$srccat-$tgtcatphr\n";
#	print "Fert=$fert\n";
	
=cut
	$tgtprephr4=join('_',@tgtpres4);
	$tgtprephr3=join('_',@tgtpres3);
	$tgtprephr2=join('_',@tgtpres2);
	$tgtprephr1=join('_',@tgtpres1);
	
	$tgtsufphr4=join('_',@tgtsufs4);
	$tgtsufphr3=join('_',@tgtsufs3);
	$tgtsufphr2=join('_',@tgtsufs2);
	$tgtsufphr1=join('_',@tgtsufs1);
=cut

# Model Fertility
	$featuresSet{"FERT_$fert"} = 1 if(&checkCompat($purpose,"FERT"));
	$featuresSet{"FERT_$srccat\_$fert"} = 1  if(&checkCompat($purpose,"FERTPOS"));
	$featuresSet{"FERT_$srcword\_$fert"} = 1 if(&checkCompat($purpose,"FERTLEX"));
	$featuresSet{"FERTR_$srcroot\_$fert"} = 1 if(&checkCompat($purpose,"FERTRLEX"));

# Correspondence of POS Tags
	$featuresSet{"POS-$srccat-$tgtcatphr"} = 1 if(&checkCompat($purpose,"POSPAIR"));
	$featuresSet{"POSCON-$srccatContext-$tgtcatContext"} = 1 if(&checkCompat($purpose,"POSPAIR2"));

# Correspondence between the prepositions (if there are )
#	if($srcprep ne "" || $tgtprepphr ne "") {
		foreach $tgtprep (@tgtpreps) {
			if($srcprep ne "")
			{
				$featuresSet{"PREP-$srcprep-$tgtprep"} = 1 if(&checkCompat($purpose,"PREPPAIR"));
			}
		}
#	}

# Correspondence between the Auxilliaries (if there are ) 
#	if($srcaux ne "" || $tgtauxphr ne "") {
		@srcauxsplits = split(/_/,$srcaux);
		foreach $tgtaux (@tgtauxs) 
		{
			@tgtauxsplits = split(/_/,$tgtaux);
			foreach $saux (@srcauxsplits) 
			{
				foreach $taux (@tgtauxsplits) 
				{
					$featuresSet{"AUX-$saux-$taux"} = 1 if(&checkCompat($purpose,"AUXPAIR"));
				}
			}
		}
#	}
		if(&checkCompat($purpose,"LEX") && &checkCompat($purpose,"PREFIX"))
		{
			$featuresSet{"prefix4_$srcpre4\_$tgtprephr4"} = 1; 
			$featuresSet{"prefix3_$srcpre3\_$tgtprephr3"} = 1; 
			$featuresSet{"prefix2_$srcpre2\_$tgtprephr2"} = 1; 
			$featuresSet{"prefix1_$srcpre1\_$tgtprephr1"} = 1; 
		}
		if(&checkCompat($purpose,"LEX") && &checkCompat($purpose,"SUFFIX"))
		{
			$featuresSet{"suffix4_$srcsuf4\_$tgtsufphr4"} = 1; 
			$featuresSet{"suffix3_$srcsuf3\_$tgtsufphr3"} = 1; 
			$featuresSet{"suffix2_$srcsuf2\_$tgtsufphr2"} = 1; 
			$featuresSet{"suffix1_$srcsuf1\_$tgtsufphr1"} = 1; 
		}
	my($DiceWord,$DiceRoot,$DiceWordnull,$DiceRootnull,$Dictionary);

# Correspondence through Dice Coefficient
	if (($fert==1) && &checkCompat($purpose,"DICECOEFF")) {
#	if (&checkCompat($purpose,"DICECOEFF")) {
		$DiceWord = $dbs{'cacheDicewd'}->{"$srcword $tgtphr"};
		if(!($DiceWord))
		{ 
			$DiceWord = $dbs{'Dicewd'}->{"$srcword $tgtphr"};
			if($DiceWord)
			{ $dbs{'cacheDicewd'}->{"$srcword $tgtphr"} = $DiceWord; }
		}
		$featuresSet{"diceword"} = $DiceWord if($DiceWord);
	}
	elsif($fert==0 && &checkCompat($purpose,"DICECOEFFNULL"))
	{
		$DiceWordnull = $dbs{'cacheDicewdnull'}->{"$srcword null"};
		if(!$DiceWordnull)
		{
			$DiceWordnull = $dbs{'Dicewdnull'}->{"$srcword null"};
			if($DiceWordnull)
			{ $dbs{'cacheDicewdnull'}->{"$srcword null"} = $DiceWordnull; }
		}
		$featuresSet{"dicewordnull"} = $DiceWordnull if($DiceWordnull); 
	}
	elsif($fert>=2 && &checkCompat($purpose,"DICECOEFF")) {
		my($maxDiceWord) = 0;
		foreach $tgtword (@tgtwords) {
			$DiceWord = $dbs{'Dicewd'}->{"$srcword $tgtword"};
			if(!($DiceWord))
			{
				$DiceWord = $dbs{'Dicewd'}->{"$srcword $tgtword"};
				if($DiceWord)
				{ $dbs{'cacheDicewd'}->{"$srcword $tgtword"} = $DiceWord; }
			}
			if($DiceWord>$maxDiceWord) {
				$maxDiceWord = $DiceWord;
			}
		}
		$featuresSet{"diceword"} = $maxDiceWord if($maxDiceWord);
	}


	
	if(&checkCompat($purpose,"LEX") && &checkCompat($purpose,"WORD2WORD_LEX"))
	{
		$featuresSet{"LEX_$srcword\_$tgtphr"} = 1;
	}



	
	if (($fert==1) && &checkCompat($purpose,"DICEROOT")) {
		$DiceRoot = $dbs{'cacheDicert'}->{"$srcroot $tgtrootphr"};
		if(!($DiceRoot))
		{ 
			$DiceRoot = $dbs{'Dicert'}->{"$srcroot $tgtrootphr"};
			if($DiceRoot)
			{ $dbs{'cacheDicert'}->{"$srcroot $tgtrootphr"} = $DiceRoot; }
		}
		$featuresSet{"diceroot"} = $DiceRoot if($DiceRoot);
	}
	elsif($fert==0 && &checkCompat($purpose,"DICEROOTNULL"))
	{
		$DiceRootnull = $dbs{'cacheDicertnull'}->{"$srcroot null"};
		if(!$DiceRootnull)
		{
			$DiceRootnull = $dbs{'Dicertnull'}->{"$srcroot null"};
			if($DiceRootnull)
			{ $dbs{'cacheDicertnull'}->{"$srcroot null"} = $DiceRootnull; }
		}
		$featuresSet{"dicerootnull"} = $DiceRootnull if($DiceRootnull); 
	}
	elsif($fert>=2 && &checkCompat($purpose,"DICEROOT")) {
		my($maxDiceRoot) = 0;
		foreach $tgtroot (@tgtroots) {
			$DiceRoot = $dbs{'Dicert'}->{"$srcroot $tgtroot"};
			if(!($DiceRoot))
			{
				$DiceRoot = $dbs{'Dicert'}->{"$srcroot $tgtroot"};
				if($DiceRoot)
				{ $dbs{'cacheDicert'}->{"$srcroot $tgtroot"} = $DiceRoot; }
			}
			if($DiceRoot>$maxDiceRoot) {
				$maxDiceRoot = $DiceRoot;
			}
		}
		$featuresSet{"diceroot"} = $maxDiceRoot if($maxDiceRoot);
	}


	if(&checkCompat($purpose,"DICTIONARY"))
	{
		foreach $tgtroot (@tgtroots) 
		{
			
			my $Dictionary = $dbs{'Dict'}->{"$srcroot $tgtroot"};
			if($srcroot eq $tgtroot)
			{
				my $Dictionary = 1;
			}
#			print $srcroot,"-->",$tgtroot,"-->",$Dictionary,"\n";
			if($Dictionary)
			{
				$featuresSet{"dictionary"} = $Dictionary;
				last;
			}
		}
	}
#	$Dictionary = $Dict{"$srcroot $tgtrootphr"};
#	if($Dictionary)
#	{ $cacheDict{"$srcroot $tgtrootphr"} = $Dictionary; }


	if(&checkCompat($purpose,"GIZAPROB1")) 
	{
		my($max_eng_hnd) = 0;
		foreach $tgtword (@tgtwords) 
		{
			$basic_eng_hnd = $dbs{'cacheBasicEngHnd'}->{"$srcword $tgtword"};
			if(!($basic_eng_hnd))
			{
				$basic_eng_hnd = $dbs{'BasicEngHnd'}->{"$srcword $tgtword"};
				if($basic_eng_hnd)
				{
					$dbs{'cacheBasicEngHnd'}->{"$srcword $tgtword"} = $basic_eng_hnd; 
				}
			}
			if($basic_eng_hnd > $max_eng_hnd) 
			{
				$max_eng_hnd = $basic_eng_hnd;
			}
		}
		$featuresSet{"basic_eng_hnd"} = $max_eng_hnd if($max_eng_hnd);



		my($max_hnd_eng) = 0;
		foreach $tgtword (@tgtwords) 
		{
			$basic_hnd_eng = $dbs{'cacheBasicHndEng'}->{"$srcword $tgtword"};
			if(!($basic_hnd_eng))
			{
				$basic_hnd_eng = $dbs{'BasicHndEng'}->{"$srcword $tgtword"};
				if($basic_hnd_eng)
				{
					$dbs{'cacheBasicHndEng'}->{"$srcword $tgtword"} = $basic_hnd_eng; 
				}
			}
			if($basic_hnd_eng > $max_hnd_eng) 
			{
				$max_hnd_eng = $basic_hnd_eng;
			}
		}
		$featuresSet{"basic_hnd_eng"} = $max_hnd_eng if($max_hnd_eng);
	}

	if(&checkCompat($purpose,"GIZAPROB2")) 
	{
		my($max_eng_hnd) = 0;
		foreach $tgtword (@tgtwords) 
		{
			$root_eng_hnd = $dbs{'cacheRootEngHnd'}->{"$srcword $tgtword"};
			if(!($root_eng_hnd))
			{
				$root_eng_hnd = $dbs{'RootEngHnd'}->{"$srcword $tgtword"};
				if($root_eng_hnd)
				{
					$dbs{'cacheRootEngHnd'}->{"$srcword $tgtword"} = $root_eng_hnd; 
				}
			}
			if($root_eng_hnd > $max_eng_hnd) 
			{
				$max_eng_hnd = $root_eng_hnd;
			}
		}
		$featuresSet{"root_eng_hnd"} = $max_eng_hnd if($max_eng_hnd);



		my($max_hnd_eng) = 0;
		foreach $tgtword (@tgtwords) 
		{
			$root_hnd_eng = $dbs{'cacheRootHndEng'}->{"$srcword $tgtword"};
			if(!($root_hnd_eng))
			{
				$root_hnd_eng = $dbs{'RootHndEng'}->{"$srcword $tgtword"};
				if($root_hnd_eng)
				{
					$dbs{'cacheRootHndEng'}->{"$srcword $tgtword"} = $root_hnd_eng; 
				}
			}
			if($root_hnd_eng > $max_hnd_eng) 
			{
				$max_hnd_eng = $root_hnd_eng;
			}
		}
		$featuresSet{"root_hnd_eng"} = $max_hnd_eng if($max_hnd_eng);
	}

	if(&checkCompat($purpose,"GIZAPRED1")) {

		$basic_eng_hnd_pred = $cacheBasicEngHndPred{"$srcword $tgtphr"};
		if(!($basic_eng_hnd_pred))
		{
			$basic_eng_hnd_pred = $BasicEngHndPred{"$srcword $tgtphr"};
			if($basic_eng_hnd_pred)
			{ $cacheBasicEngHndPred{"$srcword $tgtphr"} = $basic_eng_hnd_pred; }
		}
		$featuresSet{"basic_eng_hnd_pred"} = $basic_eng_hnd_pred;

		$basic_hnd_eng_pred = $cacheBasicHndEngPred{"$srcword $tgtphr"};
		if(!($basic_hnd_eng_pred))
		{
			$basic_hnd_eng_pred = $BasicHndEngPred{"$srcword $tgtphr"};
			if($basic_hnd_eng_pred)
			{ $cacheBasicHndEngPred{"$srcword $tgtphr"} = $basic_hnd_eng_pred; }
		}
		$featuresSet{"basic_hnd_eng_pred"} = $basic_hnd_eng_pred;

	}

	if(&checkCompat($purpose,"GIZAPRED2")) {

		$root_eng_hnd_pred = $cacheRootEngHndPred{"$srcroot $tgtrootphr"};
		if(!($root_eng_hnd_pred))
		{
			$root_eng_hnd_pred = $RootEngHndPred{"$srcroot $tgtrootphr"};
			if($root_eng_hnd_pred)
			{ $cacheRootEngHndPred{"$srcroot $tgtrootphr"} = $root_eng_hnd_pred; }
		}
		$featuresSet{"root_eng_hnd_pred"} = $root_eng_hnd_pred;


		$root_hnd_eng_pred = $cacheRootHndEngPred{"$srcroot $tgtrootphr"};
		if(!($root_hnd_eng_pred))
		{
			$root_hnd_eng_pred = $RootHndEngPred{"$srcroot $tgtrootphr"};
			if($root_hnd_eng_pred)
			{ $cacheRootHndEngPred{"$srcroot $tgtrootphr"} = $root_hnd_eng_pred; }
		}
		$featuresSet{"root_hnd_eng_pred"} = $root_hnd_eng_pred;

	}

	foreach $tgtroot (@tgtroots)
	{
		$featuresSet{"rt_$srcroot\_$tgtroot"} = 1 if(&checkCompat($purpose,"LEX") && &checkCompat($purpose,"ROOT_ROOT"));
	}

	if(&checkCompat($purpose,"LEX") && &checkCompat($purpose,"GIZA_PROB_LEX"))
	{
		if($basic_eng_hnd) { $featuresSet{"basicehp_$srcword\_$tgtphr"} = 1; }
		if($basic_hnd_eng) { $featuresSet{"basicehp_$srcword\_$tgtphr"} = 1; }
		if($root_eng_hnd) { $featuresSet{"rootehp_$srcroot\_$tgtrootphr"} = 1; }
		if($root_eng_hnd) { $featuresSet{"rootehp_$srcroot\_$tgtrootphr"} = 1; }
	}

	if(&checkCompat($purpose,"LEX") && &checkCompat($purpose,"GIZA_PRED_LEX"))
	{
		if($basic_eng_hnd_pred) { $featuresSet{"basiceh_$srcword\_$tgtphr"} = 1; }
		if($basic_hnd_eng_pred) { $featuresSet{"basiceh_$srcword\_$tgtphr"} = 1; }
		if($root_eng_hnd_pred) { $featuresSet{"rooteh_$srcroot\_$tgtrootphr"} = 1; }
		if($root_eng_hnd_pred) { $featuresSet{"rooteh_$srcroot\_$tgtrootphr"} = 1; }
	}
	

# Distance Feature
	my($dist);
	my($scrFeatures) = new Features;

	foreach $feat (keys %featuresSet) {
#print " Local Feat = $feat $featuresSet{$feat}\n";
		$this->{$feat} = $featuresSet{$feat};
	}
#print "\n\n";


	return;

}

sub getnodeLFeatures {

	my($this) = shift;
	my($sword) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($twordref) = shift;
	my($purpose) = shift;

	my(%featuresSet) = ();

#if($LFeatureDb{"$FCONF\_$engsen\_$hinsen\_$sword\_$tword"}) {

#	%featuresSet = %{$LFeatureDb{"$FCONF\_$engsen\_$hinsen\_$sword\_$tword"}};
#	foreach $feat (keys %featuresSet) {
#		$this->{$feat} = $featuresSet{$feat};
#}
# 	print "Old Set : $FCONF\_$engsen\_$hinsen\_$sword\_$tword\n";
#	return;
#}

	my($srcword,$srccat,$srcroot,$srcrole,$verbroot,$srcprep,$srcaux);
	my(@tgtwords,@tgtcats,@tgtroots,@tgtpreps,@tgtauxs);
	my($tgtphr,$tgtrootphr,$tgtcatphr,$tgtauxphr);

	$srcword = $engsen->[$sword]->{'word'};			
	$srcroot = $engsen->[$sword]->{'root'};			
	$srcroot = lc($srcroot);
	$srccat = $engsen->[$sword]->{'pos'};			
	$srcprep=lc($engsen->[$sword]->{'PREP'});
	$srcaux=lc($engsen->[$sword]->{'AUX'});


	
=cut
	my $srcpre4 = $engsen->[$sword]->{'prefix4'};
	my $srcpre3 = $engsen->[$sword]->{'prefix3'};
	my $srcpre2 = $engsen->[$sword]->{'prefix2'};
	my $srcpre1 = $engsen->[$sword]->{'prefix1'};

	my $srcsuf4 = $engsen->[$sword]->{'suffix4'};
	my $srcsuf3 = $engsen->[$sword]->{'suffix3'};
	my $srcsuf2 = $engsen->[$sword]->{'suffix2'};
	my $srcsuf1 = $engsen->[$sword]->{'suffix1'};
=cut


	
	if(@{$twordref}==0) {
# $featuresSet{"null"} = 1;
	}
	else {
		foreach $tword (@{$twordref}) {
			push(@tgtwords,$hinsen->[$tword]->{'word'});
			push(@tgtroots,$hinsen->[$tword]->{'root'});
			push(@tgtcats,$hinsen->[$tword]->{'pos'});
			push(@tgtpreps,$hinsen->[$tword]->{'PREP'}) if($hinsen->[$tword]->{'PREP'} ne "");
			push(@tgtauxs,$hinsen->[$tword]->{'AUX'}) if($hinsen->[$tword]->{'AUX'} ne "");


=cut
			push(@tgtpres4,$hinsen->[$tword]->{'prefix4'});
			push(@tgtpres3,$hinsen->[$tword]->{'prefix3'});
			push(@tgtpres2,$hinsen->[$tword]->{'prefix2'});
			push(@tgtpres1,$hinsen->[$tword]->{'prefix1'});
			
			push(@tgtsufs4,$hinsen->[$tword]->{'suffix4'});
			push(@tgtsufs3,$hinsen->[$tword]->{'suffix3'});
			push(@tgtsufs2,$hinsen->[$tword]->{'suffix2'});
			push(@tgtsufs1,$hinsen->[$tword]->{'suffix1'});
=cut
		}
	}

	my($fert) = scalar(@tgtwords);

	if($fert>2) { return; }

	$tgtphr=join('_',@tgtwords);
	$tgtrootphr=join('_',@tgtroots);
	$tgtcatphr=join('_',@tgtcats);
	$tgtprepphr=join(',',@tgtpreps);
	$tgtauxphr=join(',',@tgtauxs);
	
=cut
	$tgtprephr4=join('_',@tgtpres4);
	$tgtprephr3=join('_',@tgtpres3);
	$tgtprephr2=join('_',@tgtpres2);
	$tgtprephr1=join('_',@tgtpres1);
	
	$tgtsufphr4=join('_',@tgtsufs4);
	$tgtsufphr3=join('_',@tgtsufs3);
	$tgtsufphr2=join('_',@tgtsufs2);
	$tgtsufphr1=join('_',@tgtsufs1);
=cut

# Model Fertility
	$featuresSet{"FERT_$fert"} = 1 if(&checkCompat($purpose,"FERT"));
	$featuresSet{"FERT_$srccat\_$fert"} = 1  if(&checkCompat($purpose,"FERTPOS"));
	$featuresSet{"FERT_$srcword\_$fert"} = 1 if(&checkCompat($purpose,"FERTLEX"));
	$featuresSet{"FERTR_$srcroot\_$fert"} = 1 if(&checkCompat($purpose,"FERTRLEX"));

# Correspondence of POS Tags
	$featuresSet{"POS-$srccat-$tgtcatphr"} = 1 if(&checkCompat($purpose,"POSPAIR"));
#	$featuresSet{"POS-$srccat-$tgtcats[0]"} = 1 if(&checkCompat($purpose,"POSPAIR"));

# Correspondence between the prepositions (if there are )
#	if($srcprep ne "" || $tgtprepphr ne "") {
		foreach $tgtprep (@tgtpreps) {
			if($srcprep ne "")
			{
				$featuresSet{"PREP-$srcprep-$tgtprep"} = 1 if(&checkCompat($purpose,"PREPPAIR"));
			}
		}
#	}

# Correspondence between the Auxilliaries (if there are ) 
#	if($srcaux ne "" || $tgtauxphr ne "") {
		@srcauxsplits = split(/_/,$srcaux);
		foreach $tgtaux (@tgtauxs) 
		{
			@tgtauxsplits = split(/_/,$tgtaux);
			foreach $saux (@srcauxsplits) 
			{
				foreach $taux (@tgtauxsplits) 
				{
					$featuresSet{"AUX-$saux-$taux"} = 1 if(&checkCompat($purpose,"AUXPAIR"));
				}
			}
		}
#	}
		if(&checkCompat($purpose,"LEX") && &checkCompat($purpose,"PREFIX"))
		{
			$featuresSet{"prefix4_$srcpre4\_$tgtprephr4"} = 1; 
			$featuresSet{"prefix3_$srcpre3\_$tgtprephr3"} = 1; 
			$featuresSet{"prefix2_$srcpre2\_$tgtprephr2"} = 1; 
			$featuresSet{"prefix1_$srcpre1\_$tgtprephr1"} = 1; 
		}
		if(&checkCompat($purpose,"LEX") && &checkCompat($purpose,"SUFFIX"))
		{
			$featuresSet{"suffix4_$srcsuf4\_$tgtsufphr4"} = 1; 
			$featuresSet{"suffix3_$srcsuf3\_$tgtsufphr3"} = 1; 
			$featuresSet{"suffix2_$srcsuf2\_$tgtsufphr2"} = 1; 
			$featuresSet{"suffix1_$srcsuf1\_$tgtsufphr1"} = 1; 
		}
	my($DiceWord,$DiceRoot,$DiceWordnull,$DiceRootnull,$Dictionary);

# Correspondence through Dice Coefficient
	if (($fert==1) && &checkCompat($purpose,"DICECOEFF")) {
		$DiceWord = $dbs{'cacheDicewd'}->{"$srcword $tgtphr"};
		if(!($DiceWord))
		{ 
			$DiceWord = $dbs{'Dicewd'}->{"$srcword $tgtphr"};
			if($DiceWord)
			{ $dbs{'cacheDicewd'}->{"$srcword $tgtphr"} = $DiceWord; }
		}
		$featuresSet{"diceword"} = $DiceWord if($DiceWord);
	}
	elsif($fert==0 && &checkCompat($purpose,"DICECOEFFNULL"))
	{
		$DiceWordnull = $dbs{'cacheDicewdnull'}->{"$srcword null"};
		if(!$DiceWordnull)
		{
			$DiceWordnull = $dbs{'Dicewdnull'}->{"$srcword null"};
			if($DiceWordnull)
			{ $dbs{'cacheDicewdnull'}->{"$srcword null"} = $DiceWordnull; }
		}
		$featuresSet{"dicewordnull"} = $DiceWordnull if($DiceWordnull); 
	}
	elsif($fert==2 && &checkCompat($purpose,"DICECOEFF")) {
		my($maxDiceWord) = 0;
		foreach $tgtword (@tgtwords) {
			$DiceWord = $dbs{'Dicewd'}->{"$srcword $tgtword"};
			if(!($DiceWord))
			{
				$DiceWord = $dbs{'Dicewd'}->{"$srcword $tgtword"};
				if($DiceWord)
				{ $dbs{'cacheDicewd'}->{"$srcword $tgtword"} = $DiceWord; }
			}
			if($DiceWord>$maxDiceWord) {
				$maxDiceWord = $DiceWord;
			}
		}
		$featuresSet{"diceword"} = $maxDiceWord if($maxDiceWord);
	}


	
	if(&checkCompat($purpose,"LEX") && &checkCompat($purpose,"WORD2WORD_LEX"))
	{
		$featuresSet{"LEX_$srcword\_$tgtphr"} = 1;
	}



	
	if (($fert==1) && &checkCompat($purpose,"DICEROOT")) {
		$DiceRoot = $dbs{'cacheDicert'}->{"$srcroot $tgtrootphr"};
		if(!($DiceRoot))
		{ 
			$DiceRoot = $dbs{'Dicert'}->{"$srcroot $tgtrootphr"};
			if($DiceRoot)
			{ $dbs{'cacheDicert'}->{"$srcroot $tgtrootphr"} = $DiceRoot; }
		}
		$featuresSet{"diceroot"} = $DiceRoot if($DiceRoot);
	}
	elsif($fert==0 && &checkCompat($purpose,"DICEROOTNULL"))
	{
		$DiceRootnull = $dbs{'cacheDicertnull'}->{"$srcroot null"};
		if(!$DiceRootnull)
		{
			$DiceRootnull = $dbs{'Dicertnull'}->{"$srcroot null"};
			if($DiceRootnull)
			{ $dbs{'cacheDicertnull'}->{"$srcroot null"} = $DiceRootnull; }
		}
		$featuresSet{"dicerootnull"} = $DiceRootnull if($DiceRootnull); 
	}
	elsif($fert==2 && &checkCompat($purpose,"DICEROOT")) {
		my($maxDiceRoot) = 0;
		foreach $tgtroot (@tgtroots) {
			$DiceRoot = $dbs{'Dicert'}->{"$srcroot $tgtroot"};
			if(!($DiceRoot))
			{
				$DiceRoot = $dbs{'Dicert'}->{"$srcroot $tgtroot"};
				if($DiceRoot)
				{ $dbs{'cacheDicert'}->{"$srcroot $tgtroot"} = $DiceRoot; }
			}
			if($DiceRoot>$maxDiceRoot) {
				$maxDiceRoot = $DiceRoot;
			}
		}
		$featuresSet{"diceroot"} = $maxDiceRoot if($maxDiceRoot);
	}


	if(&checkCompat($purpose,"DICTIONARY"))
	{
		foreach $tgtroot (@tgtroots) 
		{
			
			my $Dictionary = $dbs{'Dict'}->{"$srcroot $tgtroot"};
			if($srcroot eq $tgtroot)
			{
				my $Dictionary = 1;
			}
#			print $srcroot,"-->",$tgtroot,"-->",$Dictionary,"\n";
			if($Dictionary)
			{
				$featuresSet{"dictionary"} = $Dictionary;
				last;
			}
		}
	}
#	$Dictionary = $Dict{"$srcroot $tgtrootphr"};
#	if($Dictionary)
#	{ $cacheDict{"$srcroot $tgtrootphr"} = $Dictionary; }


	if(&checkCompat($purpose,"GIZAPROB1")) 
	{
		my($max_eng_hnd) = 0;
		foreach $tgtword (@tgtwords) 
		{
			$basic_eng_hnd = $dbs{'cacheBasicEngHnd'}->{"$srcword $tgtword"};
			if(!($basic_eng_hnd))
			{
				$basic_eng_hnd = $dbs{'BasicEngHnd'}->{"$srcword $tgtword"};
				if($basic_eng_hnd)
				{
					$dbs{'cacheBasicEngHnd'}->{"$srcword $tgtword"} = $basic_eng_hnd; 
				}
			}
			if($basic_eng_hnd > $max_eng_hnd) 
			{
				$max_eng_hnd = $basic_eng_hnd;
			}
		}
		$featuresSet{"basic_eng_hnd"} = $max_eng_hnd if($max_eng_hnd);



		my($max_hnd_eng) = 0;
		foreach $tgtword (@tgtwords) 
		{
			$basic_hnd_eng = $dbs{'cacheBasicHndEng'}->{"$srcword $tgtword"};
			if(!($basic_hnd_eng))
			{
				$basic_hnd_eng = $dbs{'BasicHndEng'}->{"$srcword $tgtword"};
				if($basic_hnd_eng)
				{
					$dbs{'cacheBasicHndEng'}->{"$srcword $tgtword"} = $basic_hnd_eng; 
				}
			}
			if($basic_hnd_eng > $max_hnd_eng) 
			{
				$max_hnd_eng = $basic_hnd_eng;
			}
		}
		$featuresSet{"basic_hnd_eng"} = $max_hnd_eng if($max_hnd_eng);
	}

	if(&checkCompat($purpose,"GIZAPROB2")) 
	{
		my($max_eng_hnd) = 0;
		foreach $tgtword (@tgtwords) 
		{
			$root_eng_hnd = $dbs{'cacheRootEngHnd'}->{"$srcword $tgtword"};
			if(!($root_eng_hnd))
			{
				$root_eng_hnd = $dbs{'RootEngHnd'}->{"$srcword $tgtword"};
				if($root_eng_hnd)
				{
					$dbs{'cacheRootEngHnd'}->{"$srcword $tgtword"} = $root_eng_hnd; 
				}
			}
			if($root_eng_hnd > $max_eng_hnd) 
			{
				$max_eng_hnd = $root_eng_hnd;
			}
		}
		$featuresSet{"root_eng_hnd"} = $max_eng_hnd if($max_eng_hnd);



		my($max_hnd_eng) = 0;
		foreach $tgtword (@tgtwords) 
		{
			$root_hnd_eng = $dbs{'cacheRootHndEng'}->{"$srcword $tgtword"};
			if(!($root_hnd_eng))
			{
				$root_hnd_eng = $dbs{'RootHndEng'}->{"$srcword $tgtword"};
				if($root_hnd_eng)
				{
					$dbs{'cacheRootHndEng'}->{"$srcword $tgtword"} = $root_hnd_eng; 
				}
			}
			if($root_hnd_eng > $max_hnd_eng) 
			{
				$max_hnd_eng = $root_hnd_eng;
			}
		}
		$featuresSet{"root_hnd_eng"} = $max_hnd_eng if($max_hnd_eng);
	}

	if(&checkCompat($purpose,"GIZAPRED1")) {

		$basic_eng_hnd_pred = $cacheBasicEngHndPred{"$srcword $tgtphr"};
		if(!($basic_eng_hnd_pred))
		{
			$basic_eng_hnd_pred = $BasicEngHndPred{"$srcword $tgtphr"};
			if($basic_eng_hnd_pred)
			{ $cacheBasicEngHndPred{"$srcword $tgtphr"} = $basic_eng_hnd_pred; }
		}
		$featuresSet{"basic_eng_hnd_pred"} = $basic_eng_hnd_pred;

		$basic_hnd_eng_pred = $cacheBasicHndEngPred{"$srcword $tgtphr"};
		if(!($basic_hnd_eng_pred))
		{
			$basic_hnd_eng_pred = $BasicHndEngPred{"$srcword $tgtphr"};
			if($basic_hnd_eng_pred)
			{ $cacheBasicHndEngPred{"$srcword $tgtphr"} = $basic_hnd_eng_pred; }
		}
		$featuresSet{"basic_hnd_eng_pred"} = $basic_hnd_eng_pred;

	}

	if(&checkCompat($purpose,"GIZAPRED2")) {

		$root_eng_hnd_pred = $cacheRootEngHndPred{"$srcroot $tgtrootphr"};
		if(!($root_eng_hnd_pred))
		{
			$root_eng_hnd_pred = $RootEngHndPred{"$srcroot $tgtrootphr"};
			if($root_eng_hnd_pred)
			{ $cacheRootEngHndPred{"$srcroot $tgtrootphr"} = $root_eng_hnd_pred; }
		}
		$featuresSet{"root_eng_hnd_pred"} = $root_eng_hnd_pred;


		$root_hnd_eng_pred = $cacheRootHndEngPred{"$srcroot $tgtrootphr"};
		if(!($root_hnd_eng_pred))
		{
			$root_hnd_eng_pred = $RootHndEngPred{"$srcroot $tgtrootphr"};
			if($root_hnd_eng_pred)
			{ $cacheRootHndEngPred{"$srcroot $tgtrootphr"} = $root_hnd_eng_pred; }
		}
		$featuresSet{"root_hnd_eng_pred"} = $root_hnd_eng_pred;

	}

	foreach $tgtroot (@tgtroots)
	{
		$featuresSet{"rt_$srcroot\_$tgtroot"} = 1 if(&checkCompat($purpose,"LEX") && &checkCompat($purpose,"ROOT_ROOT"));
	}

	if(&checkCompat($purpose,"LEX") && &checkCompat($purpose,"GIZA_PROB_LEX"))
	{
		if($basic_eng_hnd) { $featuresSet{"basicehp_$srcword\_$tgtphr"} = 1; }
		if($basic_hnd_eng) { $featuresSet{"basicehp_$srcword\_$tgtphr"} = 1; }
		if($root_eng_hnd) { $featuresSet{"rootehp_$srcroot\_$tgtrootphr"} = 1; }
		if($root_eng_hnd) { $featuresSet{"rootehp_$srcroot\_$tgtrootphr"} = 1; }
	}

	if(&checkCompat($purpose,"LEX") && &checkCompat($purpose,"GIZA_PRED_LEX"))
	{
		if($basic_eng_hnd_pred) { $featuresSet{"basiceh_$srcword\_$tgtphr"} = 1; }
		if($basic_hnd_eng_pred) { $featuresSet{"basiceh_$srcword\_$tgtphr"} = 1; }
		if($root_eng_hnd_pred) { $featuresSet{"rooteh_$srcroot\_$tgtrootphr"} = 1; }
		if($root_eng_hnd_pred) { $featuresSet{"rooteh_$srcroot\_$tgtrootphr"} = 1; }
	}
	

# Distance Feature
	my($dist);
	my($scrFeatures) = new Features;

	foreach $feat (keys %featuresSet) {
#print " Local Feat = $feat $featuresSet{$feat}\n";
		$this->{$feat} = $featuresSet{$feat};
	}
#print "\n\n";


	return;

}

sub checkCompat {
	my($purpose) = $_[0];
	my($featMode) = $_[1];

	if($purpose eq "u" && $C{"$featMode"}=~/\+1$/) {
		return 1;
	}
	elsif($purpose eq "p" && $C{"$featMode"}=~/^1\+/) {
		return 1;
	}
	else {
		return 0;
	}
}

sub ifequal {

	my($srcword) = lc($_[0]);
	my($tgtword) = lc($_[1]);

	if($srcword eq $tgtword)
	{
		return 1;
	}
	return 0;
}

sub ifconsequal {

	my($srcword) = lc($_[0]);
	my($tgtword) = lc($_[1]);

	$srcword=~s/[aeiou,;\.\:\-\\\/\"\'\*\%\$]+//g;
	$tgtword=~s/[aeiou,;\.\:\-\\\/\"\'\*\%\$]+//g;

	if($srcword eq $tgtword)
	{
		return 1;
	}
	return 0;
}

sub fracoverlap {

	my($srcword) = $_[0];
	my($tgtword) = $_[1];

	if($srcword=~/^[^A-Z]/)
	{
		return 0;
	}


	$tgtword=~s/[\$\%\&\*\?\+\(\)\[\]\\\.]+//g;
	$tgtword=lc($tgtword);

	$tgtword=~s/[aeiou]//g;

	$tgtword=~s/w/t/g;
	$tgtword=~s/x/d/g;
	$tgtword=~s/k/c/g;
	$tgtword=~s/([a-z])m/$1n/g;
	$tgtword=~s/z/j/g;
	$tgtword=~s/p/f/g;

	$srcword=~s/[\$\%\&\*\?\+\(\)\[\]\\]//g;
	$srcword=lc($srcword);
	$srcword=~s/[aeiou]//g;
	$srcword=~s/([a-z])m/$1n/g;
	$srcword=~s/z/j/g;


	my ($longest_c, $longest,$strlen,$substr) = 0;
	for my $start (0..length $tgtword) {
		for my $len ( reverse $start+1 .. length $tgtword) {
			my $substr = substr($tgtword, $start, $len);

			while($srcword =~/($substr)/g)
			{
				$substr = $1;
				$strlen = length $1;
				if($strlen > $longest_c)
				{ ($longest_c, $longest) = ($strlen, $substr); }
			}
		}
	}

	if(length($srcword)==0) { return 0; }
	return (length($longest)/(length($srcword)));
}


sub verbtype {
	my($verbroot) = shift;
	if($verbroot eq "take" || $verbroot eq "be" || $verbroot eq "make")
	{ return $verbroot; }
	return;
}

sub auxtype {
	my($root) = shift;
	my($cat) = shift;

	if($cat eq "v" && ( $root eq "WA" || $root eq "kara" || $root eq "jA" || $root  eq "raha" || $root eq "banA" || $root eq "ho" || $root eq "hE" || $root eq "jAna" || $root eq "le" || $root eq "ho" || $root eq "uTA" || $root eq "xe" ))
	{ return $root; }
	return;
}

sub preptype {
	my($root) = shift;
	my($cat) = shift;
	if($cat eq "p")
	{ return $root; }
	return 0;
}

sub dotProduct {
	my($Features1) = shift;
	my($Features2) = shift;
	my($dotproduct) = 0;
	foreach $feature (keys %{$Features1})
	{
		$dotproduct += $Features1->{$feature}*$Features2->{$feature};
	}
	return $dotproduct;
}

sub difffeatures {
	my($this) = shift;
	my($Features1) = shift;
	my($Features2) = shift;

	foreach $feature (keys %{$Features1})
	{
		$this->{$feature} = $Features1->{$feature};
	}

	foreach $feature (keys %{$Features2})
	{
		$this->{$feature} -= $Features2->{$feature};
		if($this->{$features}==0) {
			delete($this->{$features});
		}
	}
}

sub difffeatures2 {
	my($this) = shift;
	my($Features1) = shift;
	my($Features2) = shift;

	foreach $feature (keys %{$Features2})
	{
		$this->{$feature} = $Features1->{$feature} - $Features2->{$feature};
	}

}

sub r {
	my ($number,$decimals) = @_;
	return substr($number+("0."."0"x$decimals."5"),
			0, $decimals+length(int($number))+1);
}

1;

sub valid_rel {
	my($prep) = shift;              
	my(@relations) = ("subj","obj","by","on","in","into","at","for","through","with","without","of","to","after","around","during","beneath","behind","from","adj","at","from","over","about","under","before","within","against","since","until","upon","among","despite","along","beyond","than","above","near","below","onto","inside","amongst","towards","besides");
	foreach $rel (@relations)
	{
		if($rel eq $prep)
		{ return 1; }
	}
	return 0;

}            


sub get_windowdist {

	my($p,$q,$i);
	my($avgdist,$totelem);
	my($win,$window);

	for($win=2;$win<=4;$win++)
	{
		$window = $win;
		for($i=$window-1;$i<$nengwords;$i++)
		{
			$avgdist = 0;
			$totelem = 0;
			for($p=$i-2+1;$p<=$i;$p++)
			{
				for($q=$p+1;$q<=$i;$q++)
				{
					if($Align->{'aln'}->[$p] ne "-" && $Align->{'aln'}->[$q] ne "-")
					{
						$dist = abs($Align->{'aln'}->[$p] - $Align->{'aln'}->[$q]);
						$totelem ++;
					}
				}
			}

		}
		if($totelem)
		{  
			$this->{"windist_$window"} += $dist/$totelem; 
		}
	}
}

sub get_bigramdirecmag {

	my($this) = shift;
	my($Align) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($conf) = shift;
	my($srcstr,$tgtstr);

	my($nengwords) = $#{$engsen->{'word'}}+1;
	my($nhinwords) = $#{$hinsen->{'word'}}+1;

	my($word1pos,$word1index,$word2pos,$word2index);
	my($word1,$word2);
	my($trunc1pos,$trunc2pos);
	my($dist,$distsrc);
	for($i=1;$i<$nengwords;$i++)
	{
		if($Align->{'aln'}->[$i] ne "-" && $Align->{'aln'}->[$i-1] ne "-")
		{
			$word2pos = $engsen->{'pos'}->[$i];
			$word2 = $engsen->{'wroot'}->[$i];
			$word2 = lc($word2);
			$word2pos =~/^(.)/g; $trunc2pos = $1;

			$word1pos = $engsen->{'pos'}->[$i-1];
			$word1 = $engsen->{'wroot'}->[$i-1];
			$word1 = lc($word1);
			$word1pos =~/^(.)/g; $trunc1pos = $1;

			$dist = $Align->{'aln'}->[$i] - $Align->{'aln'}->[$i-1];


			if($conf==1) {
				$srcstr = $word1.",".$word2;	
			}
			elsif($conf==2) {
				$srcstr = $word1pos.",".$word2pos;
			}
			elsif($conf==3) {
				$srcstr = $trunc1pos.",".$trunc2pos;
			}

			if($dist==0)
			{
				$tgtstr = "XY";
			}
			elsif($dist<0)
			{
				$tgtstr = "Y<-X";
			}
			elsif($dist>0)
			{
				$tgtstr = "X->Y";
			}

			$this->{"$srcstr\_$tgtstr"}+= 1;
		}
	}
}

sub get_vargdist {
	my($this) = shift;
	my($Varg) = shift;
	my($Align) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($conf) = shift;

	my($verbpos,$verbroot,$argroot,$argpos,$argcat,$argprep);
	my($verbtype,$truncpos,$mi,$dist);

	for($i=0;$i<=$#$Varg;$i++)
	{
		$verbpos = $Varg->[$i]->{'position'};
		$verbroot = $engsen->{'wroot'}->[$verbpos];

		for($j=0;$j<=$#{$Varg->[$i]->{'args'}};$j++)
		{
			$argpos = $Varg->[$i]->{'args'}->[$j]->{'position'};
			$argprep = $Varg->[$i]->{'args'}->[$j]->{'prep'};

			$argroot = $engsen->{'wroot'}->[$argpos];
			$argcat = $engsen->{'pos'}->[$argpos];
			$argcat =~/^(.)/;
			$truncpos = $1;

			if($Align->{'aln'}->[$verbpos] ne "-" && $Align->{'aln'}->[$argpos] ne "-")
			{
				$dist = $Align->{'aln'}->[$verbpos] - $Align->{'aln'}->[$argpos];
				$dist = &r(($dist+1)/$nhinwords,2);
				$this->{"varg_$truncpos"} = $dist;
			}
		}
	}

}

sub get_mergefeat {
	my($this) = shift;
	my($Varg) = shift;
	my($Align) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($nengwords) = $#{$engsen->{'word'}}+1;
	my($nhinwords) = $#{$hinsen->{'word'}}+1;

	my($verbpos,$verbroot,$argpos,$argroot,$argcat,$truncpos);

# Computing the One verb compositionality feature
	my($verbtype,$truncpos,$mi);
	my($j);

	for($i=0;$i<=$#$Varg;$i++)
	{
		$verbpos = $Varg->[$i]->{'position'};
		$verbroot = $engsen->{'wroot'}->[$verbpos];
		for($j=0;$j<=$#{$Varg->[$i]->{'args'}};$j++)
		{
			$argpos = $Varg->[$i]->{'args'}->[$j]->{'position'};
			$argprep = $Varg->[$i]->{'args'}->[$j]->{'prep'};


			$argroot = $engsen->{'wroot'}->[$argpos];
			$argcat = $engsen->{'pos'}->[$argpos];
			$argcat =~/^(.)/;
			$truncpos = $1;

# Merge based features

			if($Align->{'aln'}->[$verbpos] eq $Align->{'aln'}->[$argpos] || $Align->{'aln'}->[$verbpos] eq "-" || $Align->{'aln'}->[$argpos] eq "-")
			{

				$mi = 0; 

				$mi = $cacheMI{"$verbroot $argprep $argroot"};
				if(!$mi)
				{
					$mi = $MI{"$verbroot $argprep $argroot"};
					if($mi)
					{ $cacheMI{"$verbroot $argprep $argroot"} = $mi;  }
				}

				$mi = abs(int($mi + 0.5 * ($number <=> 0)));

				if($mi<3)
				{
					$this->{"merge_$truncpos\_LOW"} = 1;
				}
				elsif($mi<6)
				{
					$this->{"merge_$truncpos\_MED"} = 1;
				}
				else
				{
					$this->{"merge_$truncpos\_HIGH"} = 1;
				}
			}
		}
	}
}

sub get_depdirec {
	my($this) = shift;
	my($Dep) = shift;
	my($wordpos) = shift;
	my($Align) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($conf) = shift;
	my($nengwords) = $#{$engsen->{'word'}}+1;
	my($nhinwords) = $#{$hinsen->{'word'}}+1;

	my($childPosition);
	my($t,$dist);
	my($parentPOS,$childPOS);
	my($parent,$child);
	my($wordaln,$childaln);

	my($srcstr,$tgtstr);

	my($GCONF) = $ENV{'GCONF'};

	$parentPOS = $engsen->{'pos'}->[$wordpos];
	$parent = lc($engsen->{'wroot'}->[$wordpos]);
	$wordaln = $Align->{'aln'}->[$wordpos];
	if($wordaln ne "-") {
		$tparentPOS = $hinsen->{'pos'}->[$wordaln];
	}
	$parentPOS=~/^(.)/; $truncparentPOS = $1;

	my($minaln,$maxaln);
	$maxaln = $wordaln;
	$minaln = $wordaln;

	my($GCONF) = $ENV{'GCONF'};

	for($t=0;$t<$Dep->[$wordpos]->{'noatt'};$t++)
	{
		$childPosition = $Dep->[$wordpos]->{'attch'}->[$t];
		$childPOS = $engsen->{'pos'}->[$childPosition];
		$child = lc($engsen->{'wroot'}->[$childPosition]);
		if($childaln ne "-") {
			$childaln = $Align->{'aln'}->[$childPosition];
		}
		$tchildPOS = $hinsen->{'pos'}->[$childaln];
		$childPOS=~/^(.)/; $truncchildPOS = $1;


		if($parentPOS ne "" && $childPOS ne "" && $wordaln ne "-" && $childaln ne "-")
		{
			if($conf==1) {
				if($wordpos>$childPosition) {
					$srcstr = $child."<-".$parent;	
				}
				else {
					$srcstr = $parent."->".$child;	
				}
			}
			if($conf==2) {
				if($wordpos>$childPosition) {
					$srcstr = $childPOS."<-".$parentPOS;	
				}
				else {
					$srcstr = $parentPOS."->".$childPOS;	
				}
			}
			elsif($conf==3) {
				$srcstr = $parent.",".$child;
			}	
			elsif($conf==4) {
				$srcstr = $parentPOS.",".$childPOS;
			}	
			elsif($conf==5) {
				if($wordpos>$childPosition) {
					$srcstr = $truncchildPOS."<-".$truncparentPOS;	
				}
				else {
					$srcstr = $truncparentPOS."->".$truncchildPOS;	
				}
			}

			$dist = $wordaln - $childaln;

			if($dist>0)
			{
				$tgtstr = "Y<-X";
			}
			elsif($dist<0)
			{
				$tgtstr = "X->Y";
			}
			else
			{
				$tgtstr = "XY";
			}

			$this->{"$srcstr\_$tgtstr"}+=1;	
		}

		if($childaln ne "-" && $childaln<$minaln) { $minaln = $childaln; }
		elsif($childaln ne "-" && $childaln>$maxaln) { $maxaln = $childaln; }

		$this->get_depdirec($Dep,$childPosition,$Align,$engsen,$hinsen,$conf);

	}

	if($GCONF==11 || $GCONF==12) {
		$this->{'avgspan'} += $maxaln - $minaln;
	}
}

sub getGFeatures {

	my($this) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($Align) = shift;
	my($Varg) = shift;
	my($Dep) = shift;
	my($nengwords) = $#{$engsen->{'word'}}+1;
	my($nhinwords) = $#{$hinsen->{'word'}}+1;

	my($i,$j,$p);
	my($avvb_dist,$av,$tot,$overlap);

	my($GCONF) = $ENV{'GCONF'};

# Get Overlap and Null
	my($overlap) = 0;
	my($total) = 0;
	my(%numberpos);
	my($nonnulls) = 0;

	for($i=0;$i<$nengwords;$i++)
	{
		if($Align->{'aln'}->[$i] ne "-")
		{
			$numberpos{$Align->{'aln'}->[$i]}++;
#		print STDERR $i." ".$Align->{'aln'}->[$i]." ".$numberpos{$npos}."\n";
		}
	}

	foreach $npos (keys %numberpos)
	{
		if($numberpos{$npos}>1)
		{ $overlap+=$numberpos{$npos}*$numberpos{$npos}; }

		$nonnulls++;


		$total+= $numberpos{$npos};
	}

	if($GCONF==1 || $GCONF==2 || $GCONF==9 || $GCONF==10 || $GCONF==12 || $GCONF==14 || $GCONF==16 || $GCONF==20 || $GCONF==21 || $GCONF==23 || $GCONF==24 || $GCONF==26) {
		if($total)
		{ $this->{'overlap'} = $overlap/$total; }
	}

	if($GCONF==2) {
		$this->{'nulls'} = ($nhinwords-$nonnulls)/$nhinwords;
	}

	my($rootpos,$roothinpos);

	$rootpos = $Dep->[0]->{'root'};
	if($GCONF==2) {
		if($Align->{'aln'}->[$rootpos])
		{ $this->{"rootpos"} = $Align->{'aln'}->[$rootpos]/$nhinwords; }
	}

# avg span is computed in Dep direct, be careful
	if($GCONF==3 || $GCONF==7 || $GCONF==9 || $GCONF==14 || $GCONF==18 || $GCONF==20 || $GCONF==24) {
		$this->get_depdirec($Dep,$rootpos,$Align,$engsen,$hinsen,1);
	}
	if($GCONF==4 || $GCONF==7 || $GCONF==9 || $GCONF==14) {
		$this->get_depdirec($Dep,$rootpos,$Align,$engsen,$hinsen,2);
	}
	if($GCONF==5 || $GCONF==8 || $GCONF==10) {
		$this->get_depdirec($Dep,$rootpos,$Align,$engsen,$hinsen,3);
	}
	if($GCONF==6 || $GCONF==8 || $GCONF==10) {
		$this->get_depdirec($Dep,$rootpos,$Align,$engsen,$hinsen,4);
	}

	if($GCONF==17 || $GCONF==18 || $GCONF==19 || $GCONF==20 || $GCONF==24 || $GCONF==25 || $GCONF==26) {
		$this->get_depdirec($Dep,$rootpos,$Align,$engsen,$hinsen,5);
	}

	if($GCONF==11 || $GCONF==12) {
		$this->{'avgspan'}/=$nhinwords;
	}

	if($GCONF==13 || $GCONF==14) {
		$this->get_mergefeat($Varg,$Align,$engsen,$hinsen);
	}

#$this->get_vargdist($Varg,$Align,$engsen,$hinsen);

	if($GCONF==15 || $GCONF==16 || $GCONF==22 || $GCONF==23 || $GCONF==24) {
		$this->get_bigramdirecmag($Align,$engsen,$hinsen,1);
	}

	if($GCONF==15 || $GCONF==16) {
		$this->get_bigramdirecmag($Align,$engsen,$hinsen,2);
	}

	if($GCONF==15 || $GCONF==16 || $GCONF==21 || $GCONF==23 || $GCONF==24 || $GCONF==25 || $GCONF==26) {
		$this->get_bigramdirecmag($Align,$engsen,$hinsen,3);
	}

#$this->get_windowdist($Align,$engsen,$hinsen);


}

sub getFeatures {
	my($this) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($Align) = shift;
	my($Varg) = shift;
	my($Dep) = shift;
	my($nengwords) = $#{$engsen->{'word'}}+1;
	my($nhinwords) = $#{$hinsen->{'word'}}+1;

	my($FCONF) = $ENV{'FCONF'};

	my($i,$j,$p);	
	my($LFeatures);
	my($TFeatures);
	my($GFeatures);
	my($avvb_dist,$av,$tot,$overlap);

	for($i=0;$i<$nengwords;$i++)
	{
		$LFeatures = new Features;
		$LFeatures->getLFeatures($engsen,$hinsen,$i,$Align->{'aln'}->[$i]);
		$this->addFeatures($LFeatures);

		$TFeatures = new Features;
		$TFeatures->getTreeletFeatures($engsen,$hinsen,$i,$Dep->[$i]->{'attch'},$Align->{'aln'});
		$this->addFeatures($TFeatures);
	}


#$GFeatures = new Features;
#$GFeatures->getGFeatures($engsen,$hinsen,$Align,$Varg,$Dep);
#$this->addFeatures($GFeatures);

}

sub get_srcposition {
	my($verbnum) = shift;
	my($argnum) = shift;
	my($Varg) = shift;
	my($j);
	my($num_between) = 1;

	if($Varg->[$verbnum]->{'args'}->[$argnum]->{'position'} < $Varg->[$verbnum]->{'position'})
	{
		for($j=0;$j<$Varg->[$verbnum]->{'Nargs'};$j++)
		{
			if($Varg->[$verbnum]->{'args'}->[$argnum]->{'position'} < $Varg->[$verbnum]->{'args'}->[$j]->{'position'} && $Varg->[$verbnum]->{'args'}->[$j]->{'position'} < $Varg->[$verbnum]->{'position'})
			{
				$num_between++;
			}
			return -1*$num_between;
		}
	}
	elsif($Varg->[$verbnum]->{'args'}->[$argnum]->{'position'} > $Varg->[$verbnum]->{'position'})
	{
		for($j=0;$j<$Varg->[$verbnum]->{'Nargs'};$j++)
		{
			if($Varg->[$verbnum]->{'args'}->[$argnum]->{'position'} > $Varg->[$verbnum]->{'args'}->[$j]->{'position'} && $Varg->[$verbnum]->{'args'}->[$j]->{'position'} > $Varg->[$verbnum]->{'position'})
			{
				$num_between++;
			}
			return $num_between;
		}
	}
}

sub addFeatures {
	my($this) = shift;
	my($Feats) = shift;
	foreach $Feat (keys %{$Feats})
	{
		$this->{$Feat} += $Feats->{$Feat};
	}
}

sub getTreeletFeatures {

	my($this) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($root) = shift;	
	my($childrenRef) = shift;
	my($AlignarrRef) = shift;

	if($root == -1 || @{$childrenRef}==0) {
		return 0;
	} 

	my(@sourcePositions,%targetPos);

	push(@sourcePositions,$root);
	push(@sourcePositions,@{$childrenRef});

	my($sourcePOS) = "";
	my($pos);
	my($k) = 0;
	foreach $pos (sort {$a<=>$b} @sourcePositions) {
		$sourcePOS.=" ".$engsen->{'pos'}->[$pos];	
		if($pos == $root) {
			$sourcePOS.="*";
		}


		$tpos = $AlignarrRef->[$pos];

		if($tpos ne "-") {
			push(@targetPositions,$tpos);
			$targetPos{$tpos}.=$k."-";
		}
		$k++;
	}
	$sourcePOS=~s/^ //g;

	my($targetPOS) = "";
	foreach $pos (sort {$a<=>$b} keys %targetPos) {
#print "TargetPOS $pos $targetPos{$pos}\n";
		$targetPos{$pos}=~s/-$//g;
		$targetPOS.=" ".$targetPos{$pos};	
	}
	$targetPOS=~s/^ //g;

	$this->{"$sourcePOS\->$targetPOS"} = 1;

}

sub getLFeatures {
	my($this) = shift;
	my($engsen) = shift;
	my($hinsen) = shift;
	my($sword)= shift;
	my($tword) = shift;
	my(%featuresSet) = ();

	my($FCONF) = $ENV{'FCONF'};

	if($LFeatureDb{"$FCONF\_$engsen\_$hinsen\_$sword\_$tword"}) {

		%featuresSet = %{$LFeatureDb{"$FCONF\_$engsen\_$hinsen\_$sword\_$tword"}};
		foreach $feat (keys %featuresSet) {
			$this->{$feat} = $featuresSet{$feat};
		}
# print "Old Set : $FCONF\_$engsen\_$hinsen\_$sword\_$tword\n";
		return;
	}

	my($srcword,$srccat,$srcroot,$srcrole,$verbroot);

	$srcword = $engsen->{'word'}->[$sword];			
	$srcroot = $engsen->{'wroot'}->[$sword];			
	$srcroot = lc($srcroot);
	$srccat = $engsen->{'pos'}->[$sword];			

	if($tword eq "-")
	{
		my($srcrole);

#	if($FCONF == 2 || $FCONF == 7) {
#		$featuresSet{"null_$srccat"} = 1;
#	}

		if($FCONF == 4 || $FCONF==5 || $FCONF==6 || $FCONF==7 || $FCONF==8 || $FCONF==9 || $FCONF==10 || $FCONF==11) {
			$srccat=~/^(.)/g;
			$featuresSet{"null_$1"} = 1;
		}

		$tgtword = "null";
		$tgtcat = "null";
		$tgtroot = "null";

#return;
	}
	else
	{
		$tgtword = $hinsen->{'word'}->[$tword];			
		$tgtroot = $hinsen->{'wroot'}->[$tword];			
		$tgtcat = $hinsen->{'pos'}->[$tword];	

	}

	my($DiceWord,$DiceRoot,$DiceWordnull,$DiceRootnull,$Dictionary);

	$DiceWord = $cacheDicewd{"$srcword $tgtword"};
	if(!($DiceWord))
	{ 
		$DiceWord = $Dicewd{"$srcword $tgtword"};
		if($DiceWord)
		{ $cacheDicewd{"$srcword $tgtword"} = $DiceWord; }
	}
	if($tgtword eq "null")
	{

		$DiceWordnull = $dbs{'cacheDicewdnull'}->{"$srcword null"};
		if(!$DiceWordnull)
		{
			$DiceWordnull = $Dicewdnull{"$srcword null"};
			if($DiceWordnull)
			{ $dbs{'cacheDicewdnull'}->{"$srcword null"} = $DiceWordnull; }
		}
	}

	$DiceRoot = $cacheDicert{"$srcroot $tgtroot"};
	if(!($DiceRoot))
	{ 
		$DiceRoot = $Dicewd{"$srcroot $tgtroot"};
		if($DiceRoot)
		{ $cacheDicert{"$srcroot $tgtroot"} = $DiceRoot; }
	}
	if($tgtroot eq "null")
	{
		$DiceRootnull = $cacheDicertnull{"$srcroot null"};
		if(!$DiceRootnull)
		{
			$DiceRootnull = $Dicertnull{"$srcroot null"};
			if($DiceRootnull)
			{ $cacheDicertnull{"$srcroot null"} = $DiceRootnull; }
		}
	}

	$Dictionary = $cacheDict{"$srcroot $tgtroot"};
	if(!($Dictionary))
	{
		$Dictionary = $Dict{"$srcroot $tgtroot"};
		if($Dictionary)
		{ $cacheDict{"$srcroot $tgtroot"} = $Dictionary; }
	}

	$basic_eng_hnd = $cacheBasicEngHnd{"$srcword $tgtword"};
	if(!($basic_eng_hnd))
	{
		$basic_eng_hnd = $BasicEngHnd{"$srcword $tgtword"};
		if($basic_eng_hnd)
		{ $cacheBasicEngHnd{"$srcword $tgtword"} = $basic_eng_hnd; }
	}

	$basic_eng_hnd_pred = $cacheBasicEngHndPred{"$srcword $tgtword"};
	if(!($basic_eng_hnd_pred))
	{
		$basic_eng_hnd_pred = $BasicEngHndPred{"$srcword $tgtword"};
		if($basic_eng_hnd_pred)
		{ $cacheBasicEngHndPred{"$srcword $tgtword"} = $basic_eng_hnd_pred; }
	}

	$basic_hnd_eng = $cacheBasicHndEng{"$srcword $tgtword"};
	if(!($basic_hnd_eng))
	{
		$basic_hnd_eng = $BasicHndEng{"$srcword $tgtword"};
		if($basic_hnd_eng)
		{ $cacheBasicHndEng{"$srcword $tgtword"} = $basic_hnd_eng; }
	}

	$basic_hnd_eng_pred = $cacheBasicHndEngPred{"$srcword $tgtword"};
	if(!($basic_hnd_eng_pred))
	{
		$basic_hnd_eng_pred = $BasicHndEngPred{"$srcword $tgtword"};
		if($basic_hnd_eng_pred)
		{ $cacheBasicHndEngPred{"$srcword $tgtword"} = $basic_hnd_eng_pred; }
	}

	$root_eng_hnd = $cacheRootEngHnd{"$srcroot $tgtroot"};
	if(!($root_eng_hnd))
	{
		$root_eng_hnd = $RootEngHnd{"$srcroot $tgtroot"};
		if($root_eng_hnd)
		{ $cacheRootEngHnd{"$srcroot $tgtroot"} = $root_eng_hnd; }
	}

	$root_eng_hnd_pred = $cacheRootEngHndPred{"$srcroot $tgtroot"};
	if(!($root_eng_hnd_pred))
	{
		$root_eng_hnd_pred = $RootEngHndPred{"$srcroot $tgtroot"};
		if($root_eng_hnd_pred)
		{ $cacheRootEngHndPred{"$srcroot $tgtroot"} = $root_eng_hnd_pred; }
	}

	$root_hnd_eng = $cacheRootHndEng{"$srcroot $tgtroot"};
	if(!($root_hnd_eng))
	{
		$root_hnd_eng = $RootHndEng{"$srcroot $tgtroot"};
		if($root_hnd_eng)
		{ $cacheRootHndEng{"$srcroot $tgtroot"} = $root_hnd_eng; }
	}

	$root_hnd_eng_pred = $cacheRootHndEngPred{"$srcroot $tgtroot"};
	if(!($root_hnd_eng_pred))
	{
		$root_hnd_eng_pred = $RootHndEngPred{"$srcroot $tgtroot"};
		if($root_hnd_eng_pred)
		{ $cacheRootHndEngPred{"$srcroot $tgtroot"} = $root_hnd_eng_pred; }
	}

	if($DiceWord) { 
		if($FCONF != 2) {
#		$featuresSet{"diceword"} = $DiceWord;
		}
	}
	elsif($DiceWordnull) { 
		if($FCONF != 2) {
			$featuresSet{"diceword"} = $DiceWordnull; 
		}
		if($FCONF==1 || $FCONF==3) {
			$featuresSet{"dicewordnull"} = $DiceWordnull; 
		}
	}
#elsif($tgtword eq "null")
#{ $featuresSet{'diceword'} = 2/50000; }

	if($DiceRoot) { 
		if($FCONF != 1) {
			$featuresSet{"diceroot"} = $DiceRoot; 
		}
	}
	elsif($DiceRootnull) { 
		if($FCONF != 1) {
			$featuresSet{"diceroot"} = $DiceRootnull; 
		}
		if($FCONF==2 || $FCONF==3) {
			$featuresSet{"dicerootnull"} = $DiceRootnull; 
		}
	}
#elsif($tgtroot eq "null")
#{ $featuresSet{'diceroot'} = 2/50000; }

#if($DiceWord && $DiceRoot) { $featuresSet{'diceprod'} = sqrt($DiceWord*$DiceRoot); }

	if($Dictionary) { 
		if($FCONF==5 || $FCONF==6 || $FCONF==7 || $FCONF==8 || $FCONF==9 || $FCONF==10 || $FCONF==11) {
			$featuresSet{"dictionary"} = $Dictionary; 
		}
	}

	if($FCONF==6 || $FCONF==9 || $FCONF==10 || $FCONF==11) {
#if($FCONF==6 || $FCONF==10 || $FCONF==11) {
	$featuresSet{"rt_$srcroot\_$tgtroot"} = 1;
}


if($FCONF==9)
{
	if($basic_eng_hnd) { $featuresSet{"basic_eng_hnd"} = $basic_eng_hnd; }
	if($basic_hnd_eng) { $featuresSet{"basic_hnd_eng"} = $basic_hnd_eng; }
	if($root_eng_hnd) { $featuresSet{"root_eng_hnd"} = $root_eng_hnd; }
	if($root_hnd_eng) { $featuresSet{"root_hnd_eng"} = $root_hnd_eng; }
}

if($FCONF==11)
{
	if($basic_eng_hnd) { $featuresSet{"basicehp_$srcword\_$tgtword"} = 1; }
	if($basic_hnd_eng) { $featuresSet{"basicehp_$srcword\_$tgtword"} = 1; }
	if($root_eng_hnd) { $featuresSet{"rootehp_$srcroot\_$tgtroot"} = 1; }
	if($root_eng_hnd) { $featuresSet{"rootehp_$srcroot\_$tgtroot"} = 1; }
}

if($FCONF==10)
{
	if($basic_eng_hnd_pred) { $featuresSet{"basiceh_$srcword\_$tgtword"} = 1; }
	if($basic_hnd_eng_pred) { $featuresSet{"basiceh_$srcword\_$tgtword"} = 1; }
	if($root_eng_hnd_pred) { $featuresSet{"rooteh_$srcroot\_$tgtroot"} = 1; }
	if($root_eng_hnd_pred) { $featuresSet{"rooteh_$srcroot\_$tgtroot"} = 1; }
}

# Distance Feature
my($dist);
if($tword ne "-")
{
#	$dist = abs($sword/($#{$engsen->{'word'}}+1) - $tword/($#{$hinsen->{'word'}}+1));
#	$featuresSet{'dist'} = $dist;

#	my($totalequal,$consequal,$fracoverlap);
#	$totalequal = &ifequal($srcword,$tgtword);
#	if($totalequal) { $featuresSet{'equal'} = 1; }
#	$consequal = &ifconsequal($srcword,$tgtword);
#	if($consequal) { $featuresSet{'consequal'} = 1; }

	if($FCONF==7 || $FCONF==8 || $FCONF==9) {
		$fracoverlap = &fracoverlap($srcword,$tgtword);
		if($fracoverlap) { $featuresSet{'fracoverlap'} = 1; }
	}

}

foreach $feat (keys %featuresSet) {
	$this->{$feat} = $featuresSet{$feat};
}

$LFeatureDb{"$FCONF\_$engsen\_$hinsen\_$sword\_$tword"} = \%featuresSet;
return;

}

sub ifequal {

	my($srcword) = lc($_[0]);
	my($tgtword) = lc($_[1]);

	if($srcword eq $tgtword)
	{
		return 1;
	}
	return 0;
}

sub ifconsequal {

	my($srcword) = lc($_[0]);
	my($tgtword) = lc($_[1]);

	$srcword=~s/[aeiou,;\.\:\-\\\/\"\'\*\%\$]+//g;
	$tgtword=~s/[aeiou,;\.\:\-\\\/\"\'\*\%\$]+//g;

	if($srcword eq $tgtword)
	{
		return 1;
	}
	return 0;
}

sub fracoverlap {

	my($srcword) = $_[0];
	my($tgtword) = $_[1];

	if($srcword=~/^[^A-Z]/)
	{
		return 0;
	}


	$tgtword=~s/[\$\%\&\*\?\+\(\)\[\]\\\.]+//g;
	$tgtword=lc($tgtword);

	$tgtword=~s/[aeiou]//g;

	$tgtword=~s/w/t/g;
	$tgtword=~s/x/d/g;
	$tgtword=~s/k/c/g;
	$tgtword=~s/([a-z])m/$1n/g;
	$tgtword=~s/z/j/g;
	$tgtword=~s/p/f/g;

	$srcword=~s/[\$\%\&\*\?\+\(\)\[\]\\]//g;
	$srcword=lc($srcword);
	$srcword=~s/[aeiou]//g;
	$srcword=~s/([a-z])m/$1n/g;
	$srcword=~s/z/j/g;


	my ($longest_c, $longest,$strlen,$substr) = 0;
	for my $start (0..length $tgtword) {
		for my $len ( reverse $start+1 .. length $tgtword) {
			my $substr = substr($tgtword, $start, $len);

			while($srcword =~/($substr)/g)
			{
				$substr = $1;
				$strlen = length $1;
				if($strlen > $longest_c)
				{ ($longest_c, $longest) = ($strlen, $substr); }
			}
		}
	}

	if(length($srcword)==0) { return 0; }
	return (length($longest)/(length($srcword)));
}


sub verbtype {
	my($verbroot) = shift;
	if($verbroot eq "take" || $verbroot eq "be" || $verbroot eq "make")
	{ return $verbroot; }
	return;
}

sub auxtype {
	my($root) = shift;
	my($cat) = shift;

	if($cat eq "v" && ( $root eq "WA" || $root eq "kara" || $root eq "jA" || $root  eq "raha" || $root eq "banA" || $root eq "ho" || $root eq "hE" || $root eq "jAna" || $root eq "le" || $root eq "ho" || $root eq "uTA" || $root eq "xe" ))
	{ return $root; }
	return;
}

sub preptype {
	my($root) = shift;
	my($cat) = shift;
	if($cat eq "p")
	{ return $root; }
	return 0;
}

sub dotProduct {
	my($Features1) = shift;
	my($Features2) = shift;
	my($dotproduct) = 0;
	foreach $feature (keys %{$Features1})
	{
		$dotproduct += $Features1->{$feature}*$Features2->{$feature};
	}
	return $dotproduct;
}

sub difffeatures {
	my($this) = shift;
	my($Features1) = shift;
	my($Features2) = shift;

	foreach $feature (keys %{$Features1})
	{
		$this->{$feature} = $Features1->{$feature};
	}

	foreach $feature (keys %{$Features2})
	{
		$this->{$feature} -= $Features2->{$feature};
	}
}

sub difffeatures2 {
	my($this) = shift;
	my($Features1) = shift;
	my($Features2) = shift;

	foreach $feature (keys %{$Features2})
	{
		$this->{$feature} = $Features1->{$feature} - $Features2->{$feature};
	}

}

sub r {
	my ($number,$decimals) = @_;
	return substr($number+("0."."0"x$decimals."5"),
			0, $decimals+length(int($number))+1);
}

1;
